Zaawansowane algorytmy i struktury danych/Wykład 1: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Rytter (dyskusja | edycje)
Rytter (dyskusja | edycje)
Nie podano opisu zmian
Linia 4: Linia 4:
__TOC__
__TOC__


Tekst jest ciągiem symboli, przyjmujemy żejest on zadany tablicą x[1..k] elementami której są symbole. Liczba <math>k=|x|</math> jest długością (rozmiarem)tekstu.W większości naszych algorytmów jedyne operacje dopuszczalne na symbolach wejściowych to porównania dwóch symboli.
Tekst jest ciągiem symboli, przyjmujemy że jest on zadany tablicą x[1..k] elementami której są symbole. Liczba <math>k=|x|</math> jest długością (rozmiarem) tekstu. W większości naszych algorytmów jedyne operacje dopuszczalne na symbolach wejściowych to porównania dwóch symboli.


Postawowym problemem tekstowem jest problem ''string matchingu'' polegający na szukaniu wzorca <math>x=x[1..m]</math> wteście <math>y=y[1..n]</math>. Elementami tablic są symbole. Na kursie z ASD przerabialiśmy algorytm Knutha-Morrisa-Pratt(w skrócie KMP) i jego wariacje. Zaprezentujemy teraz bardziej zaawansowany algorytm dla tego problemu: algorytm Boyera-Moore'a (w skrócie BM). Pomimo tego, że jest jasne jak ten algorytm działa to jednak jegopełna analiza (złożoność, preprocessing) jest zawansowana.
Podstawowym problemem tekstowem jest problem ''string matchingu'' polegający na szukaniu wzorca <math>x=x[1..m]</math> wteście <math>y=y[1..n]</math>. Elementami tablic są symbole. Na kursie z ASD przerabialiśmy algorytm Knutha-Morrisa-Pratt(w skrócie KMP) i jego wariacje. Zaprezentujemy teraz bardziej zaawansowany algorytm dla tego problemu: algorytm Boyera-Moore'a (w skrócie BM). Pomimo tego, że jest jasne jak ten algorytm działa to jednak jego pełna analiza (złożoność, preprocessing) jest zawansowana.


==Algorytm Boyera-Moore'a==
==Algorytm Boyera-Moore'a==


Algorytm ''przykłada'' x do tesktu y startując od pozycji i-tej w y, sprawdzamy czy <math>x[1..m]\ =\y[i+1..i+m]</math>.  Pozycja <math>i</math>  ''wędruje'' ze strony lewej do prawej. Jednakże, w przeciwieństwie do algorytmuKMP, równość  <math>x[1..m]\ =\ y[i+1..i+m]</math> sprawdzamy od strony prawej do lewej. Zaczniemy od algorytmu naiwnego.
Algorytm ''przykłada'' x do tekstu y startując od pozycji i-tej w y, sprawdzamy czy <math>x[1..m]\ =\y[i+1..i+m]</math>.  Pozycja <math>i</math>  ''wędruje'' ze strony lewej do prawej. Jednakże, w przeciwieństwie do algorytmu KMP, równość  <math>x[1..m]\ =\ y[i+1..i+m]</math> sprawdzamy od strony prawej do lewej. Zaczniemy od algorytmu naiwnego.


{{algorytm|Naiwny-BM|algorytm_naiwny_BM|
{{algorytm|Naiwny-BM|algorytm_naiwny_BM|
Linia 68: Linia 68:
}}
}}


Udowodnimy potem, że algorytm ten ma złożoność liniową. Jednakże w przeciwieństwie do łatwejanalizy algorytmu KMP w tym przypadku analiza jest skomplikowana. Mamy tu przykład algorytmu, któregopoprawność jest dosyć oczywista, a analiza kosztu jest nietrywialna.
Udowodnimy potem, że algorytm ten ma złożoność liniową. Jednakże w przeciwieństwie do łatwe janalizy algorytmu KMP w tym przypadku analiza jest skomplikowana. Mamy tu przykład algorytmu, którego poprawność jest dosyć oczywista, a analiza kosztu jest nietrywialna.


<center>[[Grafika:Zasd_2.jpg]]<br> Rysunek 2: Historia algorytmu BM na przykładowych tekstach x, y.</center>
<center>[[Grafika:Zasd_2.jpg]]<br> Rysunek 2: Historia algorytmu BM na przykładowych tekstach x, y.</center>




<center>[[Grafika:Zasd_2.jpg]]<br> Rysunek 3: Działanie dwóch wersji algorytmu BM na przykładowych tekstach. Algorytm BM stosujący przesunięcie<math>BMShift'</math> wykonuje 30 porównań symboli więcej (rysunek z lewej strony) niż normalny algorytm BM stosującytablicę BM (rysunek prawej strony).</center>
<center>[[Grafika:Zasd_2.jpg]]<br> Rysunek 3: Działanie dwóch wersji algorytmu BM na przykładowych tekstach. Algorytm BM stosujący przesunięcie <math>BMShift'</math> wykonuje 30 porównań symboli więcej (rysunek z lewej strony) niż normalny algorytm BM stosujący tablicę BM (rysunek prawej strony).</center>


== Algorytm BM ze słabszą tablicą przesunięć ==
== Algorytm BM ze słabszą tablicą przesunięć ==
Jeśli zastąpimy tablicę <math>BMShift</math> przez <math>BMShift'</math> wówczas czas algorytmu BM staje się kwadratowy. Przykłademtekstów dla których osiągana jest wtedy złożoność kwadratowa są teksty:
Jeśli zastąpimy tablicę <math>BMShift</math> przez <math>BMShift'</math> wówczas czas algorytmu BM staje się kwadratowy. Przykładem tekstów dla których osiągana jest wtedy złożoność kwadratowa są teksty:
<center><math>x=ca(ba)^{k} \mbox{ oraz } y=a^{2.k+2}(ba)^{k}.</math></center>
<center><math>x=ca(ba)^{k} \mbox{ oraz } y=a^{2.k+2}(ba)^{k}.</math></center>


Linia 82: Linia 82:




Różnica między <math>BMShift</math> i <math>BMShift'</math> wydaje się być podobna do tej między silnymiprefisko-sufiksami i prefikso-sufiksami w algorytmie KMP. W obu przypadkach różnica sprowadza się dowykorzystania jednego bitu informacji, niezgodności dwóch symboli. Podczas gdy nie robi to istotnej różnicy wpesymistycznej złożoności algorytmu KMP, w tym przypadku jest to znacząca różnica między czasemkwadratowym i liniowym.  Porównajmy działanie algorytmu z przesunięciem  <math>BMShift'</math> i of <math>BMShift</math> na tekstach(patrz rysunek)
Różnica między <math>BMShift</math> i <math>BMShift'</math> wydaje się być podobna do tej między silnymi prefisko-sufiksami i prefikso-sufiksami w algorytmie KMP. W obu przypadkach różnica sprowadza się do wykorzystania jednego bitu informacji, niezgodności dwóch symboli. Podczas gdy nie robi to istotnej różnicy w pesymistycznej złożoności algorytmu KMP, w tym przypadku jest to znacząca różnica między czasem kwadratowym i liniowym.  Porównajmy działanie algorytmu z przesunięciem  <math>BMShift'</math> i of <math>BMShift</math> na tekstach(patrz rysunek)


<center><math>x\ =\ cababababa</math>  oraz  <math>y\ =\ aaaaaaaaaababababa</math>.</center>
<center><math>x\ =\ cababababa</math>  oraz  <math>y\ =\ aaaaaaaaaababababa</math>.</center>
Linia 88: Linia 88:
== Pewna własność kombinatoryczna tekstów ==
== Pewna własność kombinatoryczna tekstów ==


Okresem tekstu <math>x</math> jest każda liczba naturalna niezerowa <math>p</math> taka, że <math>x[i]=x[i+p]</math>, dla każdego i dlaktórego obie strony są zdefiniowane. Przez period(x) oznaczmy minimalny okres x. Okres jest {\em pełny} gdyjest dzielnikiem <math>|x|</math>.
Okresem tekstu <math>x</math> jest każda liczba naturalna niezerowa <math>p</math> taka, że <math>x[i]=x[i+p]</math>, dla każdego i dla którego obie strony są zdefiniowane. Przez period(x) oznaczmy minimalny okres x. Okres jest {\em pełny} gdy jest dzielnikiem <math>|x|</math>.


Jeśli <math>period(x)</math> jest własciwym (mniejszym od <math>|x|</math>) dzielnikeim <math>x</math>  to x nazywamy rozkładalnym, wprzeciwnym przypadku x nazywamy słowem ''pierwotnym'' (albo nierozkładalnym).
Jeśli <math>period(x)</math> jest własciwym (mniejszym od <math>|x|</math>) dzielnikeim <math>x</math>  to x nazywamy rozkładalnym, w przeciwnym przypadku x nazywamy słowem ''pierwotnym'' (albo nierozkładalnym).


Na przykład <math>ababab</math> jest rozkładalne, natomiast <math>abababa</math> jest pierwotne.
Na przykład <math>ababab</math> jest rozkładalne, natomiast <math>abababa</math> jest pierwotne.
Linia 99: Linia 99:




<center> [[Grafika:Zasd_4.jpg]]<br> Rysunek 4: Jeśli tekst x jest pierwotny to taka sytuacja jest niemozliwa (x nie może wystepowac wewnatrz tekstu xx.</center>
<center> [[Grafika:Zasd_4.jpg]]<br> Rysunek 4: Jeśli tekst x jest pierwotny to taka sytuacja jest niemożliwa (x nie może występować wewnątrz tekstu xx.</center>




Własność ta ''mówi'', że nie może zajść sytuacja przedstawiona na Rysunku 4.Dowód własności  korzysta z tzw. ''lematu o kresowości'' dla tekstów:  jeśli x ma okresy p, q oraz <math>p+q\le |x|</math> to <math>nwd(p,q)</math> jest również okresem x.  
Własność ta ''mówi'', że nie może zajść sytuacja przedstawiona na Rysunku 4.Dowód własności  korzysta z tzw. ''lematu o kresowości'' dla tekstów:  jeśli x ma okresy p, q oraz <math>p+q\le |x|</math> to <math>nwd(p,q)</math> jest również okresem x.  


Popatrzmy na rysunek, gdyby x wystepowal w xx to xx miałby dwa okresy p,q, takie, że <math>p+q\le |xx|</math>, z lematu o okresowości wynika wtedy, że xx ma okres mniejszy od <math>|x|</math> i będący dzielnikiem <math>|x|</math>. Zatem słowo x nie byłoby pierwotne, co jest sprzeczne z założeniem.\myskip Jako ćwiczenie pozostawiamy problem sprawdzania w czasie liniowym czy słowo x jest pierwotne.
Popatrzmy na rysunek, gdyby x występował w xx to xx miałby dwa okresy p,q, takie, że <math>p+q\le |xx|</math>, z lematu o okresowości wynika wtedy, że xx ma okres mniejszy od <math>|x|</math> i będący dzielnikiem <math>|x|</math>. Zatem słowo x nie byłoby pierwotne, co jest sprzeczne z założeniem. \myskip Jako ćwiczenie pozostawiamy problem sprawdzania w czasie liniowym czy słowo x jest pierwotne.


== Analiza złożoności algorytmu BM ==
== Analiza złożoności algorytmu BM ==


Dokładne oszacowanie na liczbę porównań w algorytmie BM wynosi około 3n. Dowód tego faktu jest jednakzbyt skomplikowany. Pokażemy tutaj oszacowanie górne 4n, dolne oszacowanie 3n pozostawiamy jako ćwiczenie.   
Dokładne oszacowanie na liczbę porównań w algorytmie BM wynosi około 3n. Dowód tego faktu jest jednak zbyt skomplikowany. Pokażemy tutaj oszacowanie górne 4n, dolne oszacowanie 3n pozostawiamy jako ćwiczenie.   


Jeśli się ''głębiej zastanowić'' to liniowy czasalgorytmu BM jest zdumiewający, algorytm zapomina jaka część tekstu y pasowała do wzorca x, i sprawdzawielokrotnie te same fragmenty które już poprzednio były sprawdzone z wynikem pozytywnym. Zjawisko takie niema miejsca w algorytmie KMP, gdzie raz sprawdzony pozytywnie symbol w tekście y nie jest już nigdy więcejsprawdzany.
Jeśli się ''głębiej zastanowić'' to liniowy czas algorytmu BM jest zdumiewający, algorytm zapomina jaka część tekstu y pasowała do wzorca x, i sprawdza wielokrotnie te same fragmenty które już poprzednio były sprawdzone z wynikiem pozytywnym. Zjawisko takie niema miejsca w algorytmie KMP, gdzie raz sprawdzony pozytywnie symbol w tekście y nie jest już nigdy więcej sprawdzany.




<center>[[Grafika:Zasd_5.jpg]]<br> Rysunek 5: Segment  <math>y[i+j-1.. i+m]</math> tekstu y jest aktualnym dopasowaniem, <math>v</math> oznacza najkrótszy pełny okressufiksu wzorca x, <math>v</math> jest również okresem aktualnego dopasowania. Zaciemniony obszar jest częścią tekstu,która nigdy wcześniej nie była odwiedzana (sprawdzana).</center>
<center>[[Grafika:Zasd_5.jpg]]<br> Rysunek 5: Segment  <math>y[i+j-1.. i+m]</math> tekstu y jest aktualnym dopasowaniem, <math>v</math> oznacza najkrótszy pełny okres sufiksu wzorca x, <math>v</math> jest również okresem aktualnego dopasowania. Zaciemniony obszar jest częścią tekstu, która nigdy wcześniej nie była odwiedzana (sprawdzana).</center>




Załóżmy, że w danej nieterminalnej iteracji algorytm BM sprawdza segment <math> y[i+j-1.. i+m]</math> tekstu y, anstępnie wykonuje przesunięcie<math>s=BMShift[j]</math>, gdzie <math>j>0</math> oraz<math>s>(m-j)/3</math>.
Załóżmy, że w danej nieterminalnej iteracji algorytm BM sprawdza segment <math> y[i+j-1.. i+m]</math> tekstu y, a nstępnie wykonuje przesunięcie<math>s=BMShift[j]</math>, gdzie <math>j>0</math> oraz<math>s>(m-j)/3</math>.
Przez ''aktualne dopasowanie'' rozumiemy aktualnie sprawdzany segment tekstu y bez pozycji, na której występuje niezgodność symboli, (patrz Rysunek 5).
Przez ''aktualne dopasowanie'' rozumiemy aktualnie sprawdzany segment tekstu y bez pozycji, na której występuje niezgodność symboli, (patrz Rysunek 5).


Niech <math>k</math> będzie najmniejszym pełnym okresem tekstu <math>x[m-s+1.. m]</math>, a  <math>v</math> niech będzie słowemodpowiadającym temu okresowi. Inaczej mówiąc zakładamy, że mamy taką sytuację jak na Rysunku 5).
Niech <math>k</math> będzie najmniejszym pełnym okresem tekstu <math>x[m-s+1.. m]</math>, a  <math>v</math> niech będzie słowem odpowiadającym temu okresowi. Inaczej mówiąc zakładamy, że mamy taką sytuację jak na Rysunku 5).
Zauważmy, że rozważamy tu okresowość w dwóch aspektach: jako liczbę(długość) oraz jako słowo.
Zauważmy, że rozważamy tu okresowość w dwóch aspektach: jako liczbę(długość) oraz jako słowo.


Linia 128: Linia 128:


{{lemat|||
{{lemat|||
Własność ''pierwszego odwiedzenia'' zachodzi w każdej nieterminalnejiteracji algorytmu BM.
Własność ''pierwszego odwiedzenia'' zachodzi w każdej nieterminalnej iteracji algorytmu BM.
}}
}}


Dowód będzie polegał na zauważeniu kilku drobniejszych własności. Następująca  własność wynika w sposób oczywisty z założeń: <math>v</math> jest słowem-okresem aktualnego dopasowania oraz  <math>v</math> jestsufiksem wzorca.
Dowód będzie polegał na zauważeniu kilku drobniejszych własności. Następująca  własność wynika w sposób oczywisty z założeń: <math>v</math> jest słowem-okresem aktualnego dopasowania oraz  <math>v</math> jest sufiksem wzorca.


Wprowadzimy kluczowe pojęcie ''pozycji krytycznej'' jako pozycji w aktualnym dopasowaniu<math>y[i+j+1..i+m]</math>, która jest odległa od końca aktualnego  dopasowania o wielokrotność <math>|v|</math>,oraz od początku co najmniej o <math>|v|</math>.
Wprowadzimy kluczowe pojęcie ''pozycji krytycznej'' jako pozycji w aktualnym dopasowaniu <math>y[i+j+1..i+m]</math>, która jest odległa od końca aktualnego  dopasowania o wielokrotność <math>|v|</math> ,oraz od początku co najmniej o <math>|v|</math>.


Mówimy, że poprzednie dopasowane kończyło się na pozycji <math>q</math> w tekście <math>y</math>, jeśli wpewnej poprzedniej iteracji koniec wzorca był przyłożony do pozycji <math>q</math> w <math>y</math>.
Mówimy, że poprzednie dopasowane kończyło się na pozycji <math>q</math> w tekście <math>y</math>, jeśli w pewnej poprzedniej iteracji koniec wzorca był przyłożony do pozycji <math>q</math> w <math>y</math>.


'''Własność 1''' Żadne poprzednie dopasowanie nie kończy się na pozycji krytycznej w aktualnym dopasowaniu.
'''Własność 1''' Żadne poprzednie dopasowanie nie kończy się na pozycji krytycznej w aktualnym dopasowaniu.


'''Dowód własności 1''' Dowód ma charakter ''filozoficzny'': gdyby własność 1 dla pewnejiteracji nie zachodziła to by tej iteracji nie było. Gdyby poprzednia iteracja kończyła się na pozycjikrytycznej to następnym końcem dopasowania byłaby pozycja <math>i+m+s</math>.  W ten sposób byśmy przeskoczyliaktualną iterację. Zatem własność 1 zawsze zachodzi.
'''Dowód własności 1''' Dowód ma charakter ''filozoficzny'': gdyby własność 1 dla pewnej iteracji nie zachodziła to by tej iteracji nie było. Gdyby poprzednia iteracja kończyła się na pozycji krytycznej to następnym końcem dopasowania byłaby pozycja <math>i+m+s</math>.  W ten sposób byśmy przeskoczyli aktualną iterację. Zatem własność 1 zawsze zachodzi.


'''Własność 2'''  Wielkość wspólnej częśc aktualnego dopasowania idanego poprzedniego dopasowania jest mniejsza od <math>k</math>.  
'''Własność 2'''  Wielkość wspólnej częśc aktualnego dopasowania i danego poprzedniego dopasowania jest mniejsza od <math>k</math>.  
'''Dowód własności 2'''. Z własności 1wynika, że koniec poprzedniego dopasowania nie kończy się na pozycji krytycznej. Gdyby wspólna część byławiększa niż <math>k</math> to słowo pierwotne <math>v</math> występowałoby wewnątrz słowa <math>vv</math>, co zaprzecza własności słów pierwotnych. Zatem musi zachodzić własność 2.
'''Dowód własności 2'''. Z własności 1wynika, że koniec poprzedniego dopasowania nie kończy się na pozycji krytycznej. Gdyby wspólna część była większa niż <math>k</math> to słowo pierwotne <math>v</math> występowałoby wewnątrz słowa <math>vv</math>, co zaprzecza własności słów pierwotnych. Zatem musi zachodzić własność 2.


'''Własność 3''' Jeśli poprzednie dopasowanie kończy się na pozycji <math>q</math> wewnątrz aktualnego dopasowania i zawiera się całkowicie w aktualnym dopasowaniu. Wtedy nie ma krytycznej pozycji naprawo od&nbsp;<math>q</math>.
'''Własność 3''' Jeśli poprzednie dopasowanie kończy się na pozycji <math>q</math> wewnątrz aktualnego dopasowania i zawiera się całkowicie w aktualnym dopasowaniu. Wtedy nie ma krytycznej pozycji naprawo od&nbsp;<math>q</math>.


'''Dowód własności 3.''' Przypuśćmy, że jest pewna pozycja krytyczna <math>r</math> na prawo od <math>q</math>. Wówczas<math>r-q</math> jest dobrym kandydatem na przesunięcie w Algorytmie BM. Ponieważ algorytm BM wybiera najmniejszeprzesunięcie spośród kandydatów na przesunięcie spełniających warunek1 i warunek2 otrzymamy nową pozycję<math>q1<r</math> jako koniec następnego dopasowania. Wynika stąd, że mamy sekwencję <math>q1<q2<q3<..</math>, końcowych pozycjipoprzednich dopasowań z których każda jest mniejsza od <math>r</math>. Wszystkie te liczby są różnymi liczbaminaturalnymi, w pewnym momencie jedna z nich musi być równa <math>r</math>. W tym momencie mamy poprzednie dopasowaniekończące się na pozycji krytycznej <math>r</math>. Przeczy to własności 2. Zatem własnośc 3 musi zachodzić.
'''Dowód własności 3.''' Przypuśćmy, że jest pewna pozycja krytyczna <math>r</math> na prawo od <math>q</math>. Wówczas <math>r-q</math> jest dobrym kandydatem na przesunięcie w Algorytmie BM. Ponieważ algorytm BM wybiera najmniejsze przesunięcie spośród kandydatów na przesunięcie spełniających warunek1 i warunek2 otrzymamy nową pozycję<math>q1<r</math> jako koniec następnego dopasowania. Wynika stąd, że mamy sekwencję <math>q1<q2<q3<..</math>, końcowych pozycji poprzednich dopasowań z których każda jest mniejsza od <math>r</math>. Wszystkie te liczby są różnymi liczbami naturalnymi, w pewnym momencie jedna z nich musi być równa <math>r</math>. W tym momencie mamy poprzednie dopasowanie kończące się na pozycji krytycznej <math>r</math>. Przeczy to własności 2. Zatem własność 3 musi zachodzić.


'''Dowód własności pierwszego odwiedzenia.''' Trzy własności przed chwilą udowodnione wystarczją do tego, żeby uzasadnienie własności pierwszego odwiedzenia było proste. Dowód jest przez zaprzeczenie. Przypuśćmy, że w pewnej poprzedniej iteracji odwiedziliśmy ''zabroniony'' obszar aktualnego dopasowania (zacienioną część tekstu y na Rysunku5).  Niech<math>q</math> będzie końcem tego poprzedniego dopasowania. Zatem  <math>q</math> nie jest pozycją krytyczną, na prawo od niej jestpewna pozycja krytyczna. Jest to sprzeczne z własnością 3. Kończy to dowód własności pierwszego odwiedzenia.
'''Dowód własności pierwszego odwiedzenia.''' Trzy własności przed chwilą udowodnione wystarczją do tego, żeby uzasadnienie własności pierwszego odwiedzenia było proste. Dowód jest przez zaprzeczenie. Przypuśćmy, że w pewnej poprzedniej iteracji odwiedziliśmy ''zabroniony'' obszar aktualnego dopasowania (zacienioną część tekstu y na Rysunku5).  Niech<math>q</math> będzie końcem tego poprzedniego dopasowania. Zatem  <math>q</math> nie jest pozycją krytyczną, na prawo od niej jest pewna pozycja krytyczna. Jest to sprzeczne z własnością 3. Kończy to dowód własności pierwszego odwiedzenia.


Możemy teraz przystąpić do ostatecznej analizy algorytmu BM.
Możemy teraz przystąpić do ostatecznej analizy algorytmu BM.
Linia 154: Linia 154:
'''Theorem 3.1''' [Analiza algorytmu BM]
'''Theorem 3.1''' [Analiza algorytmu BM]


Algorytm BM wykonuje co najwyżej <math>4n</math> porównań symboli do momentu znalezieniapierwszego wystąpienia wzorca lub zakończenia szukania z wynikiem negatywnym.Algorytm działa w czasie <math>O(n)</math>, współczynnik kosztu nie zależy od rozmiaru alfabetu.
Algorytm BM wykonuje co najwyżej <math>4n</math> porównań symboli do momentu znalezieniapierwszego wystąpienia wzorca lub zakończenia szukania z wynikiem negatywnym. Algorytm działa w czasie <math>O(n)</math>, współczynnik kosztu nie zależy od rozmiaru alfabetu.


Z własności ''pierwszego odwiedzenia'' wynika bezpośrednio:
Z własności ''pierwszego odwiedzenia'' wynika bezpośrednio:
jeśli  <math>s</math> jest przesunięciem w nieterminalnej iteracji, to co najwyżej <math>3.s</math> pozycji tekstu y sprawdzanych wtej iteracji było sprawdzane w poprzednich iteracjach.  
jeśli  <math>s</math> jest przesunięciem w nieterminalnej iteracji, to co najwyżej <math>3.s</math> pozycji tekstu y sprawdzanych w tej iteracji było sprawdzane w poprzednich iteracjach.  


Koszt każdej nieterminalnej iteracji możnaro zdzielić na dwie części.
Koszt każdej nieterminalnej iteracji można rozdzielić na dwie części.


(1) Koszt odwiedzenia symboli w tekście <math>y</math> po raz pierwszy,
(1) Koszt odwiedzenia symboli w tekście <math>y</math> po raz pierwszy,
Linia 182: Linia 182:
Jako ćwiczenie pozostawiamy redukcję problemu liczenia tablicy <math>PREF</math> do liczenia tablicy <math>P</math>, co już potrafimy.  
Jako ćwiczenie pozostawiamy redukcję problemu liczenia tablicy <math>PREF</math> do liczenia tablicy <math>P</math>, co już potrafimy.  


Przedstawimy niezależny interesujący algorytm liczenia tablicy <math>PREF</math>. W algorytmie liczymy tablicę PREFprzeglądając tekst od lewej do prawej. Załóżmy, że przetwarzamy pozycję  <math>j</math>-tą (gdzie <math>j>1</math>), wtedy zachodzi następujący niezmiennik (patrz Rysunek 6)
Przedstawimy niezależny interesujący algorytm liczenia tablicy <math>PREF</math>. W algorytmie liczymy tablicę PREF przeglądając tekst od lewej do prawej. Załóżmy, że przetwarzamy pozycję  <math>j</math>-tą (gdzie <math>j>1</math>), wtedy zachodzi następujący niezmiennik (patrz Rysunek 6)


wartości <math>PREF[t]</math> dla <math>t <j</math> są już policzone
wartości <math>PREF[t]</math> dla <math>t <j</math> są już policzone
Linia 188: Linia 188:
<math>s<j</math> jest pozycją maksymalizującą  <math>s + PREF[s] - 1</math>.
<math>s<j</math> jest pozycją maksymalizującą  <math>s + PREF[s] - 1</math>.


Dodajemy specjalny znacznik końca tekstu na pozycji  <math>m+1</math> w <math>x</math>.Korzystamy z dodatkowej prostej funkcji <math>\textit{Naive-Scan}(p,q)</math>:
Dodajemy specjalny znacznik końca tekstu na pozycji  <math>m+1</math> w <math>x</math>. Korzystamy z dodatkowej prostej funkcji <math>\textit{Naive-Scan}(p,q)</math>:
<center><math>\textit{Naive-Scan}(p,q)</math> = <math>\max\{k \ge 1</math> takie, że <math>x[p .. p+k-1] = x[q .. q+k-1]\}</math>.</center>
<center><math>\textit{Naive-Scan}(p,q)</math> = <math>\max\{k \ge 1</math> takie, że <math>x[p .. p+k-1] = x[q .. q+k-1]\}</math>.</center>


Linia 214: Linia 214:
==Obliczanie tablicy BMShift==
==Obliczanie tablicy BMShift==


Pokażemy że czas konstrukcji tablcy <math>BMShift</math> jest liniowy, podstawową częścią  będzieobliczanie tablicy <math>PREF</math>. Używając algorytmu liczenia <math>PREF</math> obliczamy w czasie liniowym symetryczną tablicę<math>S</math> sufisko-sufiksów: <math>S[j]</math> jest długością maksymalnego sufiksu tekstu <math>x</math> który kończy się na pozycji<math>j</math>. Tablica <math>S</math> odpowiada tablicy <math>PREF</math> obliczonej dla odwróconego wzorca <math>x^R</math>.
Pokażemy że czas konstrukcji tablicy <math>BMShift</math> jest liniowy, podstawową częścią  będzie obliczanie tablicy <math>PREF</math>. Używając algorytmu liczenia <math>PREF</math> obliczamy w czasie liniowym symetryczną tablicę <math>S</math> sufisko-sufiksów: <math>S[j]</math> jest długością maksymalnego sufiksu tekstu <math>x</math> który kończy się na pozycji<math>j</math>. Tablica <math>S</math> odpowiada tablicy <math>PREF</math> obliczonej dla odwróconego wzorca <math>x^R</math>.


{{algorytm|Sufikso-sufiksy|algorytm_sufikso_sufiksy|
{{algorytm|Sufikso-sufiksy|algorytm_sufikso_sufiksy|
<math>x^R:=</math>odwrócony wzorzec <math>x</math>;
<math>x^R:=</math> odwrócony wzorzec <math>x</math>;


oblicz tablicę <math>PREF</math> dla tekstu <math>x^R</math>;
oblicz tablicę <math>PREF</math> dla tekstu <math>x^R</math>;
Linia 225: Linia 225:
}}
}}


<center>[[Grafika:Zasd_7.jpg]]<br> Rysunek 7: Przypadek gdy <math>BMShift[j] < j</math>. Dla  <math>j=22</math>, oraz przykładowgo tekstu rozmiaru <math>m=25</math>, mamy<math>BMShift[22]\ =\ \min\{m-k\ :\ j=m-S[k]=22\}</math>. Otrzymujemy <math>m-S[k]=22</math>, zatem  <math>S[k]=3</math>. Dla  <math>k=9,\ 14,\ 22</math>,mamy <math>S[9]=S[14]=S[22]=3</math>, zatem  <math>BMShift[22] = m-22 = 25-22 = 3</math>. </center>
<center>[[Grafika:Zasd_7.jpg]]<br> Rysunek 7: Przypadek gdy <math>BMShift[j] < j</math>. Dla  <math>j=22</math>, oraz przykładowego tekstu rozmiaru <math>m=25</math>, mamy <math>BMShift[22]\ =\ \min\{m-k\ :\ j=m-S[k]=22\}</math>. Otrzymujemy <math>m-S[k]=22</math>, zatem  <math>S[k]=3</math>. Dla  <math>k=9,\ 14,\ 22</math>,mamy <math>S[9]=S[14]=S[22]=3</math>, zatem  <math>BMShift[22] = m-22 = 25-22 = 3</math>. </center>




Linia 250: Linia 250:




Dla przypadku, gdy <math>BMShift[j] > j</math> po wykonaniu powyższego algorytmu,otrzymane wartości nie muszą być poprawne. W tym przypadku heurystyka niezgodności na jednej pozycji jest ignorowana i sprowadzamy obliczenie do prefikso-sufiksów całego wzorca<math>x</math>. Załóżmy wtedy, że <math>j>1</math>, niech <math>k</math> będzie długości"maksymalnego prefiksu wzorca, który jest sufiksem całego wzorca, oraz <math>k<m-j</math>, wtedy przyjmujemy <math>BMShift[j]= m-k.</math>
Dla przypadku, gdy <math>BMShift[j] > j</math> po wykonaniu powyższego algorytmu, otrzymane wartości nie muszą być poprawne. W tym przypadku heurystyka niezgodności na jednej pozycji jest ignorowana i sprowadzamy obliczenie do prefikso-sufiksów całego wzorca <math>x</math>. Załóżmy wtedy, że <math>j>1</math>, niech <math>k</math> będzie długością maksymalnego prefiksu wzorca, który jest sufiksem całego wzorca, oraz <math>k<m-j</math>, wtedy przyjmujemy <math>BMShift[j]= m-k.</math>

Wersja z 12:03, 15 wrz 2006

Zaawansowane algorytmy tekstowe I


Tekst jest ciągiem symboli, przyjmujemy że jest on zadany tablicą x[1..k] elementami której są symbole. Liczba k=|x| jest długością (rozmiarem) tekstu. W większości naszych algorytmów jedyne operacje dopuszczalne na symbolach wejściowych to porównania dwóch symboli.

Podstawowym problemem tekstowem jest problem string matchingu polegający na szukaniu wzorca x=x[1..m] wteście y=y[1..n]. Elementami tablic są symbole. Na kursie z ASD przerabialiśmy algorytm Knutha-Morrisa-Pratt(w skrócie KMP) i jego wariacje. Zaprezentujemy teraz bardziej zaawansowany algorytm dla tego problemu: algorytm Boyera-Moore'a (w skrócie BM). Pomimo tego, że jest jasne jak ten algorytm działa to jednak jego pełna analiza (złożoność, preprocessing) jest zawansowana.

Algorytm Boyera-Moore'a

Algorytm przykłada x do tekstu y startując od pozycji i-tej w y, sprawdzamy czy Parser nie mógł rozpoznać (nieznana funkcja „\y”): {\displaystyle x[1..m]\ =\y[i+1..i+m]} . Pozycja i wędruje ze strony lewej do prawej. Jednakże, w przeciwieństwie do algorytmu KMP, równość x[1..m] = y[i+1..i+m] sprawdzamy od strony prawej do lewej. Zaczniemy od algorytmu naiwnego.

Algorytm Naiwny-BM


i:=0;
'while i<nm do
   j:=m,br>    while j>0 and x[j]=y[i+j] doj:=j1
   if j=0 then return true;
   {zachodzi niezmiennik(i,j)} i:=i+1
return false;

Jeśli zachodzi równość to stwierdzamy, że znaleźliśmy wystąpienie x i kończymy. W przeciwnym razie mamy niezmiennik:

niezmiennik(i,j): x[j+1..m]=y[i+j+1..i+m] oraz x[j]y[i+j].

Korzystając z niezmiennika liczymy większe przesunięcie niż 1. Przesunięcie s jest bezpieczne gdy jesteśmy pewni że w każdej sytuacji pomiędzy i oraz i+s nie zaczyna się żadne wystąpienie wzorca x wtekście y. Przypuśćmy, że x zaczyna od pozycji i+s (zobacz Rysunek 1, gdzie jest przedstawiony przypadek s<j.)

Zachodzi wtedy następujący warunek:

warunek1(j,s): dla każdego k j<km  s>k lub x[ks]=x[k],

warunek2(j,s): s<j  x[js]x[j] { własność niezgodności }.



Rysunek 1: Przesunięcie w algorytmie BM. Przypadek gdy s=BMShift[j]<j.


Definiujemy dwa rodzaje przesunięć, każde z nich dotyczy sufiksu wzorca zaczynającego się od pozycjij<m.

BMShift[j]=min{s>0: warunek1(j,s)},

BMShift[j]=min{s>0:warunek1(j,s)orazwarunek2(j,s)}.

Definiujemy również

BMShift[m]=BMShift[m]=mP[m]=period(x).

Algorytm {BM} jest wersją algorytmu Naiwny-BM, w którym przeunięcie i o jeden zamieniamy na przesunięcie oBMShift[j], zobacz Rysunek 2.


Algorytm BM


i:=0
while i<nm do
   j:=m;    while j>0 and x[j]=y[i+j] doj:=j1;
   if j=0 then return true;
   { niezmiennik(i,j) \} i:=i+BMShift[j];
return false;

Udowodnimy potem, że algorytm ten ma złożoność liniową. Jednakże w przeciwieństwie do łatwe janalizy algorytmu KMP w tym przypadku analiza jest skomplikowana. Mamy tu przykład algorytmu, którego poprawność jest dosyć oczywista, a analiza kosztu jest nietrywialna.


Rysunek 2: Historia algorytmu BM na przykładowych tekstach x, y.



Rysunek 3: Działanie dwóch wersji algorytmu BM na przykładowych tekstach. Algorytm BM stosujący przesunięcie BMShift wykonuje 30 porównań symboli więcej (rysunek z lewej strony) niż normalny algorytm BM stosujący tablicę BM (rysunek prawej strony).

Algorytm BM ze słabszą tablicą przesunięć

Jeśli zastąpimy tablicę BMShift przez BMShift wówczas czas algorytmu BM staje się kwadratowy. Przykładem tekstów dla których osiągana jest wtedy złożoność kwadratowa są teksty:

x=ca(ba)k oraz y=a2.k+2(ba)k.

Pozostawiamy jako ćwiczenie podanie wzoru na liczbę porównań z tablicą BMShift dla tych tekstów.


Różnica między BMShift i BMShift wydaje się być podobna do tej między silnymi prefisko-sufiksami i prefikso-sufiksami w algorytmie KMP. W obu przypadkach różnica sprowadza się do wykorzystania jednego bitu informacji, niezgodności dwóch symboli. Podczas gdy nie robi to istotnej różnicy w pesymistycznej złożoności algorytmu KMP, w tym przypadku jest to znacząca różnica między czasem kwadratowym i liniowym. Porównajmy działanie algorytmu z przesunięciem BMShift i of BMShift na tekstach(patrz rysunek)

x = cababababa oraz y = aaaaaaaaaababababa.

Pewna własność kombinatoryczna tekstów

Okresem tekstu x jest każda liczba naturalna niezerowa p taka, że x[i]=x[i+p], dla każdego i dla którego obie strony są zdefiniowane. Przez period(x) oznaczmy minimalny okres x. Okres jest {\em pełny} gdy jest dzielnikiem |x|.

Jeśli period(x) jest własciwym (mniejszym od |x|) dzielnikeim x to x nazywamy rozkładalnym, w przeciwnym przypadku x nazywamy słowem pierwotnym (albo nierozkładalnym).

Na przykład ababab jest rozkładalne, natomiast abababa jest pierwotne.

Lemat Kombinatoryczna własność słów pierwotnych

Jeśli x jest pierwotne to x nie ma wystąpienia wewnątrz xx.



Rysunek 4: Jeśli tekst x jest pierwotny to taka sytuacja jest niemożliwa (x nie może występować wewnątrz tekstu xx.


Własność ta mówi, że nie może zajść sytuacja przedstawiona na Rysunku 4.Dowód własności korzysta z tzw. lematu o kresowości dla tekstów: jeśli x ma okresy p, q oraz p+q|x| to nwd(p,q) jest również okresem x.

Popatrzmy na rysunek, gdyby x występował w xx to xx miałby dwa okresy p,q, takie, że p+q|xx|, z lematu o okresowości wynika wtedy, że xx ma okres mniejszy od |x| i będący dzielnikiem |x|. Zatem słowo x nie byłoby pierwotne, co jest sprzeczne z założeniem. \myskip Jako ćwiczenie pozostawiamy problem sprawdzania w czasie liniowym czy słowo x jest pierwotne.

Analiza złożoności algorytmu BM

Dokładne oszacowanie na liczbę porównań w algorytmie BM wynosi około 3n. Dowód tego faktu jest jednak zbyt skomplikowany. Pokażemy tutaj oszacowanie górne 4n, dolne oszacowanie 3n pozostawiamy jako ćwiczenie.

Jeśli się głębiej zastanowić to liniowy czas algorytmu BM jest zdumiewający, algorytm zapomina jaka część tekstu y pasowała do wzorca x, i sprawdza wielokrotnie te same fragmenty które już poprzednio były sprawdzone z wynikiem pozytywnym. Zjawisko takie niema miejsca w algorytmie KMP, gdzie raz sprawdzony pozytywnie symbol w tekście y nie jest już nigdy więcej sprawdzany.



Rysunek 5: Segment y[i+j1..i+m] tekstu y jest aktualnym dopasowaniem, v oznacza najkrótszy pełny okres sufiksu wzorca x, v jest również okresem aktualnego dopasowania. Zaciemniony obszar jest częścią tekstu, która nigdy wcześniej nie była odwiedzana (sprawdzana).


Załóżmy, że w danej nieterminalnej iteracji algorytm BM sprawdza segment y[i+j1..i+m] tekstu y, a nstępnie wykonuje przesunięcies=BMShift[j], gdzie j>0 orazs>(mj)/3. Przez aktualne dopasowanie rozumiemy aktualnie sprawdzany segment tekstu y bez pozycji, na której występuje niezgodność symboli, (patrz Rysunek 5).

Niech k będzie najmniejszym pełnym okresem tekstu x[ms+1..m], a v niech będzie słowem odpowiadającym temu okresowi. Inaczej mówiąc zakładamy, że mamy taką sytuację jak na Rysunku 5). Zauważmy, że rozważamy tu okresowość w dwóch aspektach: jako liczbę(długość) oraz jako słowo.

Zdefiniujmy własność pierwszego odwiedzenia:

  • pozycje w segmencie y[i+j+k..i+m2.k] nie były sprawdzane w poprzednich iteracjach.

Udowodnimy następujący silny i całkowicie nietrywialny fakt.

Lemat

Własność pierwszego odwiedzenia zachodzi w każdej nieterminalnej iteracji algorytmu BM.

Dowód będzie polegał na zauważeniu kilku drobniejszych własności. Następująca własność wynika w sposób oczywisty z założeń: v jest słowem-okresem aktualnego dopasowania oraz v jest sufiksem wzorca.

Wprowadzimy kluczowe pojęcie pozycji krytycznej jako pozycji w aktualnym dopasowaniu y[i+j+1..i+m], która jest odległa od końca aktualnego dopasowania o wielokrotność |v| ,oraz od początku co najmniej o |v|.

Mówimy, że poprzednie dopasowane kończyło się na pozycji q w tekście y, jeśli w pewnej poprzedniej iteracji koniec wzorca był przyłożony do pozycji q w y.

Własność 1 Żadne poprzednie dopasowanie nie kończy się na pozycji krytycznej w aktualnym dopasowaniu.

Dowód własności 1 Dowód ma charakter filozoficzny: gdyby własność 1 dla pewnej iteracji nie zachodziła to by tej iteracji nie było. Gdyby poprzednia iteracja kończyła się na pozycji krytycznej to następnym końcem dopasowania byłaby pozycja i+m+s. W ten sposób byśmy przeskoczyli aktualną iterację. Zatem własność 1 zawsze zachodzi.

Własność 2 Wielkość wspólnej częśc aktualnego dopasowania i danego poprzedniego dopasowania jest mniejsza od k. Dowód własności 2. Z własności 1wynika, że koniec poprzedniego dopasowania nie kończy się na pozycji krytycznej. Gdyby wspólna część była większa niż k to słowo pierwotne v występowałoby wewnątrz słowa vv, co zaprzecza własności słów pierwotnych. Zatem musi zachodzić własność 2.

Własność 3 Jeśli poprzednie dopasowanie kończy się na pozycji q wewnątrz aktualnego dopasowania i zawiera się całkowicie w aktualnym dopasowaniu. Wtedy nie ma krytycznej pozycji naprawo od q.

Dowód własności 3. Przypuśćmy, że jest pewna pozycja krytyczna r na prawo od q. Wówczas rq jest dobrym kandydatem na przesunięcie w Algorytmie BM. Ponieważ algorytm BM wybiera najmniejsze przesunięcie spośród kandydatów na przesunięcie spełniających warunek1 i warunek2 otrzymamy nową pozycjęq1<r jako koniec następnego dopasowania. Wynika stąd, że mamy sekwencję q1<q2<q3<.., końcowych pozycji poprzednich dopasowań z których każda jest mniejsza od r. Wszystkie te liczby są różnymi liczbami naturalnymi, w pewnym momencie jedna z nich musi być równa r. W tym momencie mamy poprzednie dopasowanie kończące się na pozycji krytycznej r. Przeczy to własności 2. Zatem własność 3 musi zachodzić.

Dowód własności pierwszego odwiedzenia. Trzy własności przed chwilą udowodnione wystarczją do tego, żeby uzasadnienie własności pierwszego odwiedzenia było proste. Dowód jest przez zaprzeczenie. Przypuśćmy, że w pewnej poprzedniej iteracji odwiedziliśmy zabroniony obszar aktualnego dopasowania (zacienioną część tekstu y na Rysunku5). Niechq będzie końcem tego poprzedniego dopasowania. Zatem q nie jest pozycją krytyczną, na prawo od niej jest pewna pozycja krytyczna. Jest to sprzeczne z własnością 3. Kończy to dowód własności pierwszego odwiedzenia.

Możemy teraz przystąpić do ostatecznej analizy algorytmu BM.

Theorem 3.1 [Analiza algorytmu BM]

Algorytm BM wykonuje co najwyżej 4n porównań symboli do momentu znalezieniapierwszego wystąpienia wzorca lub zakończenia szukania z wynikiem negatywnym. Algorytm działa w czasie O(n), współczynnik kosztu nie zależy od rozmiaru alfabetu.

Z własności pierwszego odwiedzenia wynika bezpośrednio: jeśli s jest przesunięciem w nieterminalnej iteracji, to co najwyżej 3.s pozycji tekstu y sprawdzanych w tej iteracji było sprawdzane w poprzednich iteracjach.

Koszt każdej nieterminalnej iteracji można rozdzielić na dwie części.

(1) Koszt odwiedzenia symboli w tekście y po raz pierwszy, (2) Potrojone przesunięcie.

Sumaryczna liczba porównań symboli typu (1) wynosi co najwyżej n, sumaryczna liczba porównań typu (2)wynosi co najwyżej3.(nm), ponieważ suma przesunięć nie przekracza nm. Dodatkowo może dojść m porównań w terminalej iteracji. Zatem w sumie liczba porównań jest ograniczona przez:

n+3(nm)+m4.n.


Tablica Prefikso-Prefiksów

W fazie preprocessingu algorytmu BM (obliczanie tablicy BMShift) potrzebny będzie algorym liczenia tablicy prefikso-prefiksów. Modyfikacją tablicy prefikso-sufiksów jest tablica prefikso-prefiksów: PREF[i]jest długośćią najdłuższego prefiksu tekstu x, którego wystąpienie rozpoczyna się na pozycji i.Bardziej formalnie:

PREF[i]=max{j: x[i..i+j1] jest prefiksem x \}.

Rysunek 6: Typowa sytuacja w algorytmie Prefikso-Prefiksy. Liczymy PREF dla nowej pozycji j, zakładając, że znamy wartości tablicy PREF dla pozycji wcześniejszych.

Przykład

Dla x = abababababb mamy:

PREF[1..11] = [11, 0, 8, 0, 6, 0, 4, 0, 2, 0, 0].

Jako ćwiczenie pozostawiamy redukcję problemu liczenia tablicy PREF do liczenia tablicy P, co już potrafimy.

Przedstawimy niezależny interesujący algorytm liczenia tablicy PREF. W algorytmie liczymy tablicę PREF przeglądając tekst od lewej do prawej. Załóżmy, że przetwarzamy pozycję j-tą (gdzie j>1), wtedy zachodzi następujący niezmiennik (patrz Rysunek 6)

wartości PREF[t] dla t<j są już policzone

s<j jest pozycją maksymalizującą s+PREF[s]1.

Dodajemy specjalny znacznik końca tekstu na pozycji m+1 w x. Korzystamy z dodatkowej prostej funkcji NaiveScan(p,q):

NaiveScan(p,q) = max{k1 takie, że x[p..p+k1]=x[q..q+k1]}.


Jeśli nie ma takiego k>0 to NaiveScan(p,q)=0. Wartość PREF[1] nie jest dla nas interesująca.


Algorytm Prefikso-Prefiksy


PREF[1]:=0; s:=1;
for j:=2 to mdo
   k:=js+1; r:=s+PREF[s]1;
   if r<j then
      PREF[j]:=NaiveScan(j,1);
      if PREF[j]>0 then s:=j;
   else if PREF[k]+k<PREF[s] then
      PREF[j]:=PREF[k]
   else
      x:=NaiveScan(r+1,rj+2);
      PREF[j]:=rj+1+x;s:=j;


Najważniejszą częścią algorytmu jest przekopiowywanie, w pewnych sytuacjach, wartości PREF[k] wcześniejpoliczonych na PREF[j]. Dzieje się to wtedy, gdy Pref[s] jest duże i PREF[js+1] jest małe (js+1 jest wartością j przeskalowaną względem s).

Obliczanie tablicy BMShift

Pokażemy że czas konstrukcji tablicy BMShift jest liniowy, podstawową częścią będzie obliczanie tablicy PREF. Używając algorytmu liczenia PREF obliczamy w czasie liniowym symetryczną tablicę S sufisko-sufiksów: S[j] jest długością maksymalnego sufiksu tekstu x który kończy się na pozycjij. Tablica S odpowiada tablicy PREF obliczonej dla odwróconego wzorca xR.

Algorytm Sufikso-sufiksy


xR:= odwrócony wzorzec x;

oblicz tablicę PREF dla tekstu xR;

for each {i} do S[i]:=PREF[mi+1];



Rysunek 7: Przypadek gdy BMShift[j]<j. Dla j=22, oraz przykładowego tekstu rozmiaru m=25, mamy BMShift[22] = min{mk : j=mS[k]=22}. Otrzymujemy mS[k]=22, zatem S[k]=3. Dla k=9, 14, 22,mamy S[9]=S[14]=S[22]=3, zatem BMShift[22]=m22=2522=3.


Obserwacja. Jeśli BMShift[j]=mk<j, to S[k]=mj.


Przykład

Dla j=22 i przykładowego wzorca x na Rysunku 7 mamy:

BMShift[j]=3, oraz S[253]=mj=3.


Korzystając z powyższej obserwacji przesunięcia w algorytmie BM obliczane są następująco. Inicjalizujemy BMShift[j]:=m dla każdego j.


Algorytm Oblicz-BMShift


for k:=1 to n1 do
   j:=mS[k]; BMShift[j]:=mk


Dla przypadku, gdy BMShift[j]>j po wykonaniu powyższego algorytmu, otrzymane wartości nie muszą być poprawne. W tym przypadku heurystyka niezgodności na jednej pozycji jest ignorowana i sprowadzamy obliczenie do prefikso-sufiksów całego wzorca x. Załóżmy wtedy, że j>1, niech k będzie długością maksymalnego prefiksu wzorca, który jest sufiksem całego wzorca, oraz k<mj, wtedy przyjmujemy BMShift[j]=mk.