Der Boyer-Moore Algorithmus Hauptseminar Pattern-Matching und Textalgorithmen 29.10.2002 Thomas Hellwig Der Naive Algorithmus Um auf den Boyer-Moore Algorithmus hinzuleiten, betrachten wir zuerst das grundsätzliche Verfahren, ein Muster P der Länge n in einem Text T der Länge m zu finden. Der naive Algorithmus vergleicht das Muster sukzessive von links nach rechts mit dem Text und schiebt es bei einem Mismatch oder bei vollständiger Übereinstimmung um eine Position weiter. Dafür benötigt er im schlechtesten Falle O(nm) Zeit. Der Boyer-Moore Algorithmus arbeitet im Prinzip genau wie der naive Algorithmus, er beinhaltet jedoch drei wichtige Strategien. Die bad character rule Der Boyer-Moore Algorithmus vergleicht das Muster von rechts nach links mit dem Text. Ein Zeichen des Textes, welches einen Mismatch auslöst, wird als bad character bezeichnet. Wenn die Position des letzten Vorkommens des bad characters im Muster bekannt ist, kann dieses soweit geschoben werden, dass der bad character im Muster unter dem bad character des Textes zu liegen kommt. Bsp. T: abbabac P: babac babac Der Vergleich b-c liefert einen Mismatch. Das Zeichen b kommt im Muster an den Positionen 1 und 2 vor, d.h. dass das Muster so weit verschoben werden kann, dass das letzte b aus P auf das Textsymbol b ausgerichtet ist, also um zwei Positionen. 1
Die strong good suffix rule Nicht immer liefert die bad character rule ein gutes Ergebnis. In folgender Situation ergibt der Vergleich a-b einen Mismatch. Eine Ausrichtung des letzten Vorkommens des a im Muster auf das a im Text würde eine negative Verschiebung ergeben. Besser ist es, die größtmögliche Schiebedistanz aus der Struktur des Musters abzuleiten. Die Strategie richtet sich danach, ob das bereits übereingestimmte Suffix t noch an anderer Stelle im Muster vorkommt. Fall1: t kommt an anderer Stelle vor, so dass t kein Suffix von P ist und das Zeichen links von t ein anderes als links von t ist. Bsp. T: abcabab P: cabab cabab Das Suffix ab hat bereits übereingestimmt. Das Muster kann soweit verschoben werden, bis das nächste Vorkommen von ab im Muster auf die Textsymbole ab ausgerichtet ist, also um zwei Positionen. Fall2: Es kommt nur ein Suffix von t am Anfang von P vor. Bsp. T: aabababa P: abbab abbab Hier hat das Suffix bab übereingestimmt. Es gibt im Muster zwar kein weiteres Vorkommen von bab, es kann aber um drei Positionen geschoben werden, da ein Präfix des Musters (ab) mit einem Suffix von bab übereinstimmt. Fall3: Weder t noch ein Suffix von t kommen an anderer Stelle im Muster vor. Bsp. T: abcabcbaab P: cbaab cbaab In diesem Fall stimmt das Suffix ab überein. Es gibt im Muster kein weiteres Vorkommen von ab, daher kann das Muster um n Positionen geschoben werden. Preprocessing für die bad character rule Sei A das verwendete Alphabet und x ein Zeichen aus A, dann liefert die Funktion R(x) entweder das letzte Vorkommen von x im Muster bzw. 0, wenn x nicht im Muster vorkommt. Die Werte von R(x) werden berechnet, indem das Muster von links nach rechts durchlaufen wird und die aktuelle Position für jedes Zeichen gespeichert wird. Als Grundlage dient eine nach den Zeichen indizierte Tabelle. Die Schiebedistanz bei einem Mismatch an Position k berechnet sich dann folgendermaßen: max(1, k R(x)) 2
Preprocessing strong good suffix rule Vorbetrachtung: Definition Z-Box: Der Z-Algorithmus Eine Z-Box Z i ist die Länge der längsten Zeichenkette, die eine Kopie eines Präfix des Suchmusters ist und an der Position i beginnt. Der Algorithmus zur Berechnung der Z-Boxes untersucht Zeichen für Zeichen, ob an der aktuellen Position i eine Kopie eines Präfix des Strings beginnt. Ist dies der Fall, haben wir eine Z-box gefunden und es wird an der Stelle i + 1 weiterverglichen. Das linke Ende einer Z-Box, die an Position r endet, wird mit l markiert. Bei der Berechnung können nun drei Fälle auftreten: Fall 1: Wir befinden uns in keiner Z-Box, d.h. i > r: Wir müssen Zeichen für Zeichen mit dem Präfix des Strings vergleichen. Fall 2a: Wir befinden uns in einer Z-Box, d.h. i <= r. Da wir uns in einer bereits gefundenen Z-Box ( ) und somit in einer Kopie eines Präfix des Strings befinden, können wir die Informationen nutzen, die wir dort schon gewonnen haben. Finden wir zum Beispiel an der i entsprechenden Stelle i eine Z-Box ( ), so werden l und r nicht verändert, wenn Z(i ) <, d.h. also wenn nicht über r hinausgeht. i l i r Fall 2b: Wir befinden uns in einer Z-Box, d.h. i <= r Es liegen die selben Bedingungen wie in 2a) vor, aber es gilt Z(i ) >=, d.h. also, ragt über r hinaus. Wir müssen bei den Zeichen rechts von r untersuchen, ob sie noch zu gehören; bei den Zeichen innerhalb von sind jedoch keine Vergleiche nötig.? i l i r Dadurch, dass der Z-Algorithmus bereits gewonnene Informationen nutzt, erreicht er eine Laufzeit von O(n). 3
Die Behandlung von Fall 1 der good suffix rule, dass nämlich t noch an anderer Stelle im Muster vorkommt, wird folgendermaßen vorbereitet: Definition von L (i): Für jedes i gibt L (i) die rechteste Position in P an, an der P[i n] gleich einem Suffix von P[1 L (i)] und das Zeichen links dieses Suffixes nicht gleich dem Zeichen P[i-1] ist. Bsp. P: cabdabdab L (8) = 3 Wenn das Zeichen P[i-1] einen Mismatch verursacht und L (i) > 0 ist, wird das Muster um n - L (i) Positionen geschoben. Definition von Nj(P): Nj(P) ist die Länge des längsten Suffixes von P[1 j], das zugleich ein Suffix von P ist. Nj(P) wird N-Box genannt. Bsp. P: cabdabdab N 3 (P) = 2, N 6 (P) = 5 Die Werte von Nj(P) werden mit dem sogenannten N-Algorithmus berechnet, der analog zum oben betrachteten Z-Algorithmus verfährt. Der Algorithmus zur Berechnung der N-Boxen untersucht von rechts beginnend Zeichen für Zeichen, ob an der aktuellen Position j eine Kopie eines Suffix des Suchmusters endet. Ist dies der Fall, so wurde eine N-Box gefunden und es wird an Position j-1 weiter verglichen. Die N-box, die am weitesten nach links reicht wird an ihrer linken Seite mit l und an ihrer rechten Seite mit einem r markiert. Der Algorithmus zur Berechnung der N-Boxen benötigt auch O(n) Zeit. Theorem: L (i) ist der grösste Index j<n, so dass gilt: Nj(P) = Länge von P[i n] = n-i+1 i = n-nj(p)+1 Die Werte von L (i) können in linearer Zeit aus den Werten von Nj(P) mit folgendem Algorithmus berechnet werden: for i = 1 to n do L (i) = 0; for j = 1 to n - 1 do i = n - Nj(P) + 1; L (i) = j; end; Der Fall 2, dass also t nicht als Ganzes an anderer Stelle im Muster vorkommt, d.h. L (i) = 0 ist, wird wie folgt vorbereitet: Definition von l (i): l (i) ist die Länge des längsten Suffix in P[i n], das auch Präfix von P ist. Wenn es nicht existiert, ist l (i) = 0. Die Werte von l (i) können in linearer Zeit aus den Werten von Nj(P) mit folgendem Algorithmus berechnet werden: 4
tmp = 0; for j = 0 to n - 1 do if Nj(P) = j + 1 do tmp = j + 1; l (n - j) = tmp; end; In der Suchphase werden die eben definierten Werte wie folgt verwendet: Bei einem Mismatch an Position i-1, wobei L (i) > 0 ist, wird das Muster um n - L (i) Positionen geschoben. Bei einem Mismatch an Position i-1, wobei L (i) = 0 ist, wird das Muster um n - l (i) Positionen geschoben. Wenn ein Treffer erzielt wurde, wird das Muster um n - l (2) geschoben. Analyse Wenn das Muster nicht im Text vorkommt, hat der Boyer-Moore Algorithmus in der Suchphase eine Laufzeit von O(m). Im allgemeinen Fall sind höchstens O(nm) Vergleiche notwendig, wenn z.b. T = aaaa und P = a ist. Diese worst-case Laufzeit lässt sich jedoch durch einige einfache Änderungen auf O(m) Zeit reduzieren. Ist das Alphabet groß im Vergleich zur Länge des Musters, so nähert sich die Laufzeit des Algorithmus dem best-case von O(m/n) Zeit an. In der Praxis ist also eine sublineare Laufzeit zu erwarten. Zusammenfassung Der Boyer-Moore Algorithmus verwendet zwei Strategien, um bei einem Mismatch die maximale Schiebedistanz des Musters zu ermitteln: die bad character rule und die strong good suffix rule. Beide Strategien können Verschiebungen um n bewirken: die bad character rule, wenn das erste verglichene Textsymbol nicht im Muster vorkommt und die good suffix rule, wenn die übereinstimmenden Textsymbole nicht an anderer Stelle im Muster vorkommen. Der Boyer-Moore Algorithmus liefert bei großen Alphabeten die besten Ergebnisse. Eine Beispielanwendung ist die Suchfunktion bei Emacs. 5
This document was created with Win2PDF available at http://www.daneprairie.com. The unregistered version of Win2PDF is for evaluation or non-commercial use only.