Zadaniem wyszukiwania maksymalnego prefikso-sufiksu jest znalezienie ciągu tekstowego, który jest jest zarówno prefiksem jak i sufiksem przeszukiwanego tekstu.
Poniżej przedstawione zostały dwa podejścia rozwiązania tego problemu.
Algorytm naiwny wyszukiwania maksymalnego prefikso-sufiksu
Najprostszym podejściem jest porównanie każdego właściwego prefiksu z sufiksem. Minimalna długość właściwego prefiksu wynosi zero, a maksymalna długość to length – 1. Tak więc iterujemy po każdej długości i sprawdzamy, czy właściwy prefiks tego rozmiaru pasuje do sufiksu tego samego rozmiaru. Jeśli pasują, odpowiednio aktualizujemy wynik.
Złożoność czasowa algorytmu to O(n2), a pamięciowa to O(1).
# defnicja funkcji maksymalnego prefikso-sufiksu z użyciem metody naiwnej def longestPrefixSuffix(s): res = 0 n = len(s) # iteracja po wszystkich możliwych długościach ciągu tekstowego for length in range(1, n): # Index początkowy szukanego prefixu i = 0 # Index początkowy szukanego sufixu j = n - length flag = True # Porównanie prefixu oraz sufixu for k in range(length): if s[i + k] != s[j + k]: flag = False break # Aktualizacja wyniku, jeśli ciągi tekstowe pasują if flag: res = length return res s = "ababab" print(longestPrefixSuffix(s))
Użycie algorytmu KMP dla wyszukiwania maksymalnego prefikso-sufiksu
Metoda ta polega na wykorzystaniu etapu wstępnego przetwarzania algorytmu KMP (Knuth-Morris-Pratt) do wyszukiwania wzorców. W tym etapie budujemy tablicę lps, w której każdy indeks i przechowuje długość najdłuższego właściwego prefiksu podciągu str[0…i], który jest również sufiksem tego samego podciągu. Tak więc ostatni indeks tablicy lps będzie przechowywał długość najdłuższego prefiksu, który jest również sufiksem całego ciągu.
Złożoność czasowa algorytmu to O(n), a pamięciowa to O(n).
# defnicja funkcji maksymalnego prefikso-sufiksu z użyciem algorytmu KMP def longestPrefixSuffix(s): n = len(s) lps = [0] * n # len przechowuje najdłuższy prefix, któryc jest również sufixem dla poprzedniego indexu length = 0 # lps[0] jest zawsze 0 lps[0] = 0 i = 1 while i < n: # jeśli znaki się zgadzają to zwiększ długość lps if s[i] == s[length]: length += 1 lps[i] = length i += 1 # w przypadku gdy się nie zgadzają else: if length != 0: # Zaaktualizuj długość poprzedniego indexu lps, abu uniknąć niepotrzebnych porównań length = lps[length - 1] else: # jeśli nie znaleziono psaującego predixu, ustaw wartość lps[i] = 0 lps[i] = 0 i += 1 # Ostatni element tablicy lps przechowuje długość najdłuższego prefixu, który jest również sufixem przeszukiwanego ciągu tekstowego return lps[n - 1] s = "ababab" print(longestPrefixSuffix(s))