Algorytm KMP – implementacja w języku Python

1
Przykład 1

materiale omawiającym algorytm Knutha‑Morrisa‑PrattaPAWg1Xbykmateriale omawiającym algorytm Knutha‑Morrisa‑Pratta możemy znaleźć zapisany za pomocą pseudokodu algorytm oraz dokładną analizę jego działania. W tym e‑materiale stworzymy implementację tego algorytmu. Najpierw napiszemy funkcję, której zadaniem będzie zbudowanie tablicy częściowych dopasowań. Tablicy tej potrzebujemy, aby efektywnie przeprowadzać próby dopasowań wzorca w tekście:

Linia 1. def budowa podkreślnik tablicy podkreślnik KMP otwórz nawias okrągły wzorzec zamknij nawias okrągły dwukropek. Linia 2. rozmiar podkreślnik tablicy znak równości len otwórz nawias okrągły wzorzec zamknij nawias okrągły plus 1. Linia 3. tablica znak równości otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk rozmiar podkreślnik tablicy kratka deklarujemy tablicę o 1 większą od wzorca przecinek wypełnioną 0. Linia 4. poz znak równości tablica otwórz nawias kwadratowy 0 zamknij nawias kwadratowy znak równości minus 1 kratka na pierwszej pozycji ustawiamy wartownika. Linia 6. for i in range otwórz nawias okrągły 1 przecinek rozmiar podkreślnik tablicy zamknij nawias okrągły dwukropek kratka iterujemy po wszystkich prefiksach wzorca przecinek. Linia 8. while poz zamknij nawias ostrokątny minus 1 and wzorzec otwórz nawias kwadratowy poz zamknij nawias kwadratowy wykrzyknik znak równości wzorzec otwórz nawias kwadratowy i minus 1 zamknij nawias kwadratowy dwukropek kratka dopóki możemy znaleźć dłuższy prefikso minus sufiks. Linia 9. poz znak równości tablica otwórz nawias kwadratowy poz zamknij nawias kwadratowy. Linia 10. poz plus znak równości 1. Linia 12. if i znak równości znak równości rozmiar podkreślnik tablicy minus 1 or wzorzec otwórz nawias kwadratowy i zamknij nawias kwadratowy wykrzyknik znak równości wzorzec otwórz nawias kwadratowy poz zamknij nawias kwadratowy dwukropek. Linia 13. tablica otwórz nawias kwadratowy i zamknij nawias kwadratowy znak równości poz kratka zapisujemy szerokość znalezionego prefikso minus sufiksu przecinek jeżeli element przecinek. Linia 14. kratka który występuje po znalezionym prefikso minus sufiksie jest taki sam przecinek. Linia 15. kratka jak po obecnym prefiksie. Linia 16. else dwukropek. Linia 17. tablica otwórz nawias kwadratowy i zamknij nawias kwadratowy znak równości tablica otwórz nawias kwadratowy poz zamknij nawias kwadratowy kratka zapisujemy w tablicy tę samą wartość przecinek która jest zapisana przy elemencie. Linia 18. kratka na pozycji równej szerokości prefikso minus sufiksu. Linia 19. return tablica.

Następnie zdefiniujmy funkcję, która, używając tablicy, będzie realizowała wyszukiwanie wzorca w tekście. Korzysta ona z wyżej zdefiniowanej funkcji do budowania tablicy częściowych dopasowań. W kodzie użyjemy funkcji enumerateenumerate()enumerate w celu iterowania po znakach w tekście:

Linia 1. def szukaj podkreślnik algorytmem podkreślnik KMP otwórz nawias okrągły tekst przecinek wzorzec zamknij nawias okrągły dwukropek. Linia 3. tablica podkreślnik T znak równości budowa podkreślnik tablicy podkreślnik KMP otwórz nawias okrągły wzorzec zamknij nawias okrągły kratka budujemy tablicę częściowych dopasowań. Linia 4. dop znak równości 0 kratka indeks końca obecnie dopasowanej części wzorca. Linia 5. wynikowy podkreślnik indeks znak równości minus 1. Linia 6. for indeks przecinek znak podkreślnik S in enumerate otwórz nawias okrągły tekst zamknij nawias okrągły dwukropek. Linia 7. while dop zamknij nawias ostrokątny minus 1 and wzorzec otwórz nawias kwadratowy dop zamknij nawias kwadratowy wykrzyknik znak równości znak podkreślnik S dwukropek kratka jeżeli znaleźliśmy niedopasowanie przecinek to cofamy się po indeksach. Linia 8. dop znak równości tablica podkreślnik T otwórz nawias kwadratowy dop zamknij nawias kwadratowy kratka w tablica podkreślnik T aż do napotkania wartownika otwórz nawias okrągły minus 1 zamknij nawias okrągły. Linia 9. dop plus znak równości 1 kratka lub znalezienia znaku odpowiadającego znak podkreślnik S. Linia 11. if dop znak równości znak równości len otwórz nawias okrągły wzorzec zamknij nawias okrągły dwukropek kratka jeżeli indeks dopasowania wzorca znak równości znak równości długość wzorca przecinek. Linia 12. wynikowy podkreślnik indeks znak równości indeks minus len otwórz nawias okrągły wzorzec zamknij nawias okrągły plus 1 kratka to znaleźliśmy dopasowanie. Linia 13. break. Linia 14. return wynikowy podkreślnik indeks.

Pełna wersja programu wraz z kilkoma przykładami wykonań funkcji:

Linia 1. def budowa podkreślnik tablicy podkreślnik KMP otwórz nawias okrągły wzorzec zamknij nawias okrągły dwukropek. Linia 2. rozmiar podkreślnik tablicy znak równości len otwórz nawias okrągły wzorzec zamknij nawias okrągły plus 1. Linia 3. tablica znak równości otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk rozmiar podkreślnik tablicy. Linia 4. poz znak równości tablica otwórz nawias kwadratowy 0 zamknij nawias kwadratowy znak równości minus 1. Linia 6. for i in range otwórz nawias okrągły 1 przecinek rozmiar podkreślnik tablicy zamknij nawias okrągły dwukropek. Linia 7. while poz zamknij nawias ostrokątny minus 1 and wzorzec otwórz nawias kwadratowy poz zamknij nawias kwadratowy wykrzyknik znak równości wzorzec otwórz nawias kwadratowy i minus 1 zamknij nawias kwadratowy dwukropek. Linia 8. poz znak równości tablica otwórz nawias kwadratowy poz zamknij nawias kwadratowy. Linia 9. poz plus znak równości 1. Linia 11. if i znak równości znak równości rozmiar podkreślnik tablicy minus 1 or wzorzec otwórz nawias kwadratowy i zamknij nawias kwadratowy wykrzyknik znak równości wzorzec otwórz nawias kwadratowy poz zamknij nawias kwadratowy dwukropek. Linia 12. tablica otwórz nawias kwadratowy i zamknij nawias kwadratowy znak równości poz. Linia 13. else dwukropek. Linia 14. tablica otwórz nawias kwadratowy i zamknij nawias kwadratowy znak równości tablica otwórz nawias kwadratowy poz zamknij nawias kwadratowy. Linia 16. return tablica. Linia 19. def szukaj podkreślnik algorytmem podkreślnik KMP otwórz nawias okrągły tekst przecinek wzorzec zamknij nawias okrągły dwukropek. Linia 21. tablica podkreślnik T znak równości budowa podkreślnik tablicy podkreślnik KMP otwórz nawias okrągły wzorzec zamknij nawias okrągły. Linia 22. dop znak równości 0. Linia 23. wynikowy podkreślnik indeks znak równości minus 1. Linia 24. for indeks przecinek znak podkreślnik S in enumerate otwórz nawias okrągły tekst zamknij nawias okrągły dwukropek. Linia 25. while dop zamknij nawias ostrokątny minus 1 and wzorzec otwórz nawias kwadratowy dop zamknij nawias kwadratowy wykrzyknik znak równości znak podkreślnik S dwukropek. Linia 26. dop znak równości tablica podkreślnik T otwórz nawias kwadratowy dop zamknij nawias kwadratowy. Linia 27. dop plus znak równości 1. Linia 28. if dop znak równości znak równości len otwórz nawias okrągły wzorzec zamknij nawias okrągły dwukropek. Linia 29. wynikowy podkreślnik indeks znak równości indeks minus len otwórz nawias okrągły wzorzec zamknij nawias okrągły plus 1. Linia 30. break. Linia 31. return wynikowy podkreślnik indeks. Linia 34. kratka Działanie funkcji budującej tablicę dla przykładowych wzorców. Linia 35. print otwórz nawias okrągły budowa podkreślnik tablicy podkreślnik KMP otwórz nawias okrągły cudzysłów ADCDADC cudzysłów zamknij nawias okrągły zamknij nawias okrągły. Linia 36. kratka otwórz nawias kwadratowy minus 1 przecinek 0 przecinek 0 przecinek 0 przecinek minus 1 przecinek 0 przecinek 0 przecinek 3 zamknij nawias kwadratowy. Linia 38. print otwórz nawias okrągły budowa podkreślnik tablicy podkreślnik KMP otwórz nawias okrągły cudzysłów AAAAAAAAA cudzysłów zamknij nawias okrągły zamknij nawias okrągły. Linia 39. kratka otwórz nawias kwadratowy minus 1 przecinek minus 1 przecinek minus 1 przecinek minus 1 przecinek minus 1 przecinek minus 1 przecinek minus 1 przecinek minus 1 przecinek minus 1 przecinek 8 zamknij nawias kwadratowy. Linia 41. print otwórz nawias okrągły budowa podkreślnik tablicy podkreślnik KMP otwórz nawias okrągły cudzysłów ASDGORKASDF cudzysłów zamknij nawias okrągły zamknij nawias okrągły. Linia 42. kratka otwórz nawias kwadratowy minus 1 przecinek 0 przecinek 0 przecinek 0 przecinek 0 przecinek 0 przecinek 0 przecinek minus 1 przecinek 0 przecinek 0 przecinek 3 przecinek 0 zamknij nawias kwadratowy. Linia 44. print otwórz nawias okrągły budowa podkreślnik tablicy podkreślnik KMP otwórz nawias okrągły cudzysłów ASDFORKASDFO cudzysłów zamknij nawias okrągły zamknij nawias okrągły. Linia 45. kratka otwórz nawias kwadratowy minus 1 przecinek 0 przecinek 0 przecinek 0 przecinek 0 przecinek 0 przecinek 0 przecinek minus 1 przecinek 0 przecinek 0 przecinek 0 przecinek 0 przecinek 5 zamknij nawias kwadratowy. Linia 47. kratka Szukanie dopasowań wzorca w tekście. Linia 48. szukany podkreślnik W znak równości cudzysłów ADCDADC cudzysłów. Linia 49. lancuch podkreślnik S znak równości cudzysłów ADC ADCDAD ADCDADCDADCE cudzysłów. Linia 50. print otwórz nawias okrągły szukaj podkreślnik algorytmem podkreślnik KMP otwórz nawias okrągły lancuch podkreślnik S przecinek szukany podkreślnik W zamknij nawias okrągły zamknij nawias okrągły. Linia 51. kratka 11. Linia 53. kratka przykład sprawdzenia za pomocą wbudowanej metody find. Linia 54. print otwórz nawias okrągły lancuch podkreślnik S kropka find otwórz nawias okrągły szukany podkreślnik W zamknij nawias okrągły zamknij nawias okrągły. Linia 55. kratka 11.
Dla zainteresowanych

Metoda find() w języku Python realizuje wyszukiwanie tekstu za pomocą zmodyfikowanego algorytmu Boyer‑Moor‑Horspoolalgorytm Boyer‑Moore‑HorsepoolBoyer‑Moor‑Horspool – więcej informacji na ten temat można znaleźć w kodzie źródłowym CPython.

Słownik

enumerate()
enumerate()

funkcja w języku Python służąca do generowania indeksu i wartości odpowiadającej temu indeksowi w liście

metoda naiwna
metoda naiwna

określana również jako brute force; sprawdza wszystkie możliwe dopasowania wzorca w tekście

algorytm Boyer‑Moore‑Horsepool
algorytm Boyer‑Moore‑Horsepool

jest to ulepszenie algorytmu Boyera‑Moore'a; podobnie jak algorytm KMP analizuje wzorzec w celu znalezienia maksymalnego skoku w analizie tekstu po nieudanym dopasowaniu; porównanie wzorca z fragmentem tekstu odbywa się od końca wzorca; średnia złożoność czasowa tego algorytmu to O=(długość wzorcaalfabet) i w praktyce jest on znacznie szybszy od rozwiązania naiwnego