Textalgorithmen

Vorlesung im Wintersemester 2003/04 Otto-von-Guericke-Universit¨at Magdeburg Fakult¨at fur¨ Informatik

Ralf Stiebe [email protected]

Inhaltsverzeichnis

Einleitung 4

0 Begriffe und Notationen 6

1 Exakte Suche nach einem Wort 8 1.1 Naiver Algorithmus ...... 8 1.2 R¨ander und Perioden ...... 9 1.3 Der Algorithmus von Knuth-Morris-Pratt ...... 12 1.4 Suche mit deterministischen endlichen Automaten ...... 15 1.5 Boyer-Moore-Algorithmus ...... 17 1.6 Apostolico-Giancarlo-Algorithmus ...... 22 1.7 Algorithmus von Vishkin ...... 25 1.8 Der Shift-And-Algorithmus ...... 29 1.9 Algorithmen mit Suffixautomaten ...... 30 1.10 Karp-Rabin-Algorithmus ...... 33 1.11 Eine untere Schranke fur¨ Algorithmen zur Wortsuche ...... 35

2 Exakte Suche nach komplexen Mustern 38 2.1 Suche nach endlich vielen W¨ortern ...... 38 2.2 Suche nach zweidimensionalen Bildern ...... 44 2.3 Suche nach regul¨aren Ausdrucken...... ¨ 48 2.4 Einige Spezialf¨alle regul¨arer Ausdrucke...... ¨ 51

3 Inexakte Suche 54 3.1 Einleitung ...... 54 3.2 L¨osung durch dynamische Programmierung ...... 56 3.3 Alignments mit beschr¨ankter Fehlerzahl ...... 63 3.4 Alignments mit Lucken(gaps)...... ¨ 66 3.5 L¨osung mit linearem Platzbedarf ...... 68 3.6 L¨osung in subquadratischer Zeit ...... 69 3.7 Multiple Alignments ...... 72

4 Indexieren von Texten 77 4.1 Einfuhrung¨ ...... 77 4.2 Datenstrukturen fur¨ Indexe ...... 77 4.2.1 Suffixb¨aume ...... 77 4.2.2 Suffix-Arrays ...... 79

1 4.2.3 Varianten und Erweiterungen ...... 79 4.3 Konstruktion von Suffixb¨aumen ...... 80 4.3.1 Naiver Algorithmus ...... 81 4.3.2 Algorithmus von McCreight ...... 82 4.3.3 Online-Algorithmus von Ukkonen ...... 86 4.4 Konstruktion von Suffix-Arrays ...... 86 4.4.1 Konstruktion durch Verfeinerung ...... 87 4.4.2 Skew Algorithmus von K¨arkk¨ainen und Sanders ...... 89 4.5 Anwendungen von Suffixb¨aumen und Suffix-Arrays ...... 91 4.5.1 Wiederholte Suche in festem Text ...... 91 4.5.2 L¨angstes gemeinsames Teilwort ...... 92 4.5.3 Ziv-Lempel-Kompression ...... 93 4.5.4 Burrows-Wheeler-Transformation ...... 93

Literaturverzeichnis 96

2 3 Einleitung

Die Verarbeitung langer Zeichenketten (Strings, Texte) ist eine der grundlegenden Aufgaben in der Informatik. Es ist deshalb wenig verwunderlich, daß bereits ab 1970 zahlreiche Probleme aus diesem Gebiet formuliert und effizient gel¨ost wurden. Neue Herausforderungen ergaben sich in jungerer¨ Zeit durch das Aufkommen des Internet und der Bioinformatik. Diese Vorlesung soll eine Einfuhrung¨ in einige wichtige Probleme und Algorithmen fur¨ Zeichenketten geben. Sie gliedert sich in folgende Abschnitte:

1. Exakte Wortsuche: Gegeben sind W¨orter P (Pattern) und T (Text). Gesucht sind alle Vorkommen von P in T . Wir geben verschiedene Algorithmen an, die dieses Problem effizient l¨osen. Außerdem betrachten wir das Problem der Suche nach einer endlichen Menge von W¨ortern.

2. Suche nach regul¨aren Ausdrucken:¨ Gegeben sind ein Text T und ein regul¨arer Ausdruck α. Gesucht sind Teilw¨orter von T , die in der von α definierten Sprache enthalten sind.

3. Suffixb¨aume und Suffixarrays: Diese Datenstrukturen speichern eine Zeichenkette S so, daß man einen schnellen Zugriff auf jedes Teilwort von S hat. Im Suffixbaum werden alle Suffixe von S in einem Baum gespeichert. Im Suffixarray wird die lexikografische Ordnung der Suffixe von S gespeichert. Wir behandeln effiziente Algorithmen von zur Konstruktion von Suffixb¨aumen und Suffixarrays. Wichtigste Anwendung beider Datenstrukturen ist die wiederholte Suche in einem kon- stanten Text T der L¨ange n. Ist der Suffixbaum fur¨ T konstruiert, so kann die Suche nach einem Wort P der L¨ange m mit einem Aufwand von O(m), also unabh¨angig von n, erledigt werden. Weitere Anwendungen sind die Suche nach Regularit¨aten in Tex- ten (z.B. lange Wiederholungen, sehr h¨aufige Teilw¨orter) sowie die Burrows-Wheeler- Transformation.

4. Ahnlichkeit¨ von Zeichenketten: Das Finden von Ahnlichkeiten¨ in zwei oder mehr Zei- chenketten ist von großer Bedeutung in der Bioinformatik. Die einfachste Aufgabe dieses Typs ist die Bestimmung des Levenshtein-Abstandes (): Gegeben sind zwei W¨orter S1 und S2. Wie viele Operationen der Form Ersetzen/Einfugen/Streichen¨ eines Zeichens ben¨otigt man, um S1 in S2 umzuwandeln? Dieses Skript entstand zu einer Vorlesung im Rahmen der theoretischen Informatik. Neben der Vermittlung der Algorithmen stehen deshalb Korrektheitsbeweise und Laufzeitabsch¨atzun- gen im Vordergrund.

4 Literatur

In den letzten Jahren sind einige Bucher¨ (in englischer Sprache) uber¨ Textalgorithmen er- schienen, u.a. von Apostolico und Galil [1], Crochemore und Rytter [3, 4], Gusfield [6], Na- varro und Raffinot [12] Smyth [14] und Stephen [13]. Auf franz¨osisch gibt es ein Buch von Crochemore, Hancart und Lecroq [5]. Die exakte Wortsuche wird außerdem in zahlreichen allgemeinen Buchern¨ uber¨ Algorithmen betrachtet. Besonders ausfuhrlich¨ geschieht dies im Buch von Heun [7]. Dieses Skript orientiert sich am Buch von Gusfield [6], das ein sehr gut geschriebenes Lehr- buch ist und außerdem einen umfassenden Einblick in die Anwendung von Textalgorithmen in der Bioinformatik vermittelt. Zahlreiche Quellen gibt es auch im Internet. Hier seien nur drei genannt:

• http://www.dei.unipd.it/~stelo/ eine umfangreiche Link-Sammlung von Stefano Lonardi,

• http://www-igm.univ-mlv.fr/~lecroq/lec en.html die Homepage von Thierry Lecroq mit einer umfangreichen Pr¨asentation (einschließlich Animationen) von Algorithmen zur exakten Wortsuche und zum Sequenzvergleich sowie einer umfassenden Bibliographie zu Textalgorithmen.

• http://dcc.uchile.cl/ gnavarro/eindex.html die Homepage von Gonzalo Navarro mit zahlreichen Originalarbeiten und Ubersichts-¨ artikeln aus den letzten Jahren sowie einigen nutzlichen¨ Programmen.

5 Kapitel 0

Begriffe und Notationen

Es werden die ublicherweise¨ in einer Grundvorlesung Algorithmen und Datenstrukturen ver- mittelten Kenntnisse vorausgesetzt. Die Notation von Algorithmen in Pseudocode folgt den Konventionen aus dem Standard-Lehrbuch Introduction to Algorithms von Cormen, Leiserson und Rivest [2]. Insbesondere wird der Rumpf einer Schleife durch die Tiefe der Einruckung¨ erkennbar. Bei der Bestimmung von Laufzeiten gehen wir davon aus, daß auf Speicherplatz in kon- stanter Zeit zugegriffen werden kann und fur¨ Zahlen in der Gr¨oßenordnung der betrachte- ten Wortl¨angen die arithmetischen Grundoperationen in konstanter Zeit ausgefuhrt¨ werden k¨onnen (unit cost model). Fur¨ ein Wort S uber¨ einem Alphabet Σ wird die L¨ange von S durch |S| bezeichnet. Die M¨achtigkeit einer Menge M bzw. der Betrag einer reellen Zahl z werden ebenfalls mit |M| bzw. |z| bezeichnet. Die Bedeutung ergibt sich aus dem Kontext. Das Wort der L¨ange 0 heißt das leere Wort und wird mit ε bezeichnet. Es seien u und v W¨orter. Gilt u = u1vu2, so nennt man v ein Teilwort oder Infix von u. Gilt u = vu2, so nennt man v ein Pr¨afix von u. Gilt u = u1v, so nennt man v ein Suffix von u. Ist v ein Teilwort (bzw. Pr¨afix bzw. Suffix) von u mit v 6= u, so nennt man v ein echtes Teilwort (bzw. echtes Pr¨afix bzw. echtes Suffix) von u. Fur¨ 1 ≤ i ≤ |u| ist u[i] das Zeichen an der Stelle i von u. Das Teilwort von der Stelle i bis zur Stelle j von u ist u[i . . . j]. Gilt i > j oder i > |u|, so ist u[i . . . j] per definitionem das leere Wort. Die Menge aller W¨orter uber¨ einem Alphabet Σ bezeichnen wir mit Σ∗, die Menge aller nichtleeren W¨orter mit Σ+. Mit ur bezeichnen wir das Wort S von rechts nach links gelesen. Gilt u = ur, so nennt man u ein Palindrom . Eine grundlegende Operation ist der Vergleich zweier Buchstaben. Ergibt sich bei einem solchen Vergleich eine Ubereinstimmung,¨ so sprechen wir von einem Match , anderenfalls von einem Mismatch . ∗ Es sei (Σ, <) ein total geordnetes Alphabet. Die lexikografische Ordnung

+ 1. ε

∗ 2. Aus a < b folgt aα

3. Aus α

6 Schließlich ben¨otigen wir noch den Begriff des endlichen Automaten. Ausfuhrlich¨ werden diese Stukturen in einfuhrenden¨ Buchern¨ zur Theoretischen Informatik (z.B. [8]) behandelt. Ein nichtdeterministischer endlicher Automat mit ε-Transitionen (NEA) ist ein Quintupel A = (Σ, Z, δ, I, Q), wobei Σ ein Alphabet, Z eine endliche Zustandsmenge, δ ⊆ Z × (Σ ∪ {ε}) × Z eine Uberf¨ uhrungsrelation¨ oder Menge von Transitionen, I ⊆ Z eine Menge von Startzust¨anden, Q ⊆ Z eine Menge von akzeptierenden Zust¨anden sind. Ein NEA wird h¨aufig durch seinen Graphen dargestellt. Dabei werden ein Zustand durch einen Knoten, eine Transition durch eine gerichtete und beschriftete Kante, ein Startzustand durch einen Pfeil von außen und ein Endzustand durch einen Doppelkreis gekennzeichnet. Die ε-Hulle¨ δ0 von A ist wie folgt definiert:

0 1. δ0 := {(z, ε, z): z ∈ Z}, 0 0 0 0 0 2. δi+1 := {(y, ε, z): ∃z ((y, ε, z ) ∈ δi+1 ∧ (z , ε, z) ∈ δ}, fur¨ 0 ≤ i, ∞ ∞ 0 S 0 S 0 3. δ := δi = δi . i=0 i=0 Die Relation δ wird wie folgt zur Relation δ∗ ⊆ Z × Σ∗ × Z erweitert:

1. δn+1 := {(y, wa, z): w ∈ Σn ∧ a ∈ Σ ∧ ∃z0∃z00((y, w, z0) ∈ δn ∧ (z0, a, z00) ∈ δ ∧ (z00, ε, z) ∈ δ0)}, fur¨ n ≥ 0,

∞ 2. δ∗ := S δn. n=0 Anschaulich gesprochen, ist (y, w, z) genau dann in δ∗, wenn es im Graphen des Automaten einen Weg vom Knoten y zum Knoten z mit der Beschriftung w gibt. Die vom NEA A = (Σ, Z, δ, I, Q) akzeptierte Sprache ist

∗ ∗ L(A) = {w ∈ Σ : ∃z1∃z2(z1 ∈ I ∧ z2 ∈ Q ∧ (z1, w, z2) ∈ δ }.

Ein NEA heißt (partieller) deterministischer endlicher Automat (DEA), wenn δ eine (par- tielle) Funktion δ : Z × Σ → Z ist und I genau einen Zustand enth¨alt. Es ist bekannt, daß es zu jedem NEA einen ¨aquivalenten DEA gibt, der aber exponentiell gr¨oßer sein kann.

7 Kapitel 1

Exakte Suche nach einem Wort

Wir betrachten die folgende grundlegende Aufgabenstellung: Gegeben sind ein Suchwort (pattern) P und ein Text T uber¨ einem Alphabet Σ mit |P | = m, |T | = n, |Σ| = σ. Gesucht sind alle Vorkommen von P in T . Als erstes betrachten wir die bekanntesten Algorithmen: den naiven (brute force) Algorithmus, sowie die Algorithmen von Knuth-Morris-Pratt und Boyer-Moore. Diese drei Algorithmen haben die gemeinsame Idee, das Suchwort uber¨ den Text zu schieben und durch zeichenweise Vergleiche die Vorkommen zu finden. Anschließend betrachten wir einige weitere Algorithmen mit alternativen L¨osungsans¨atzen. Neben der Komplexit¨at fur¨ den schlechtesten Fall betrachten wir gelegentlich auch die Komplexit¨at des durchschnittlichen Falles. Dabei sind alle m¨oglichen Eingaben gleichgewich- tet.

1.1 Naiver Algorithmus

Man testet fur¨ jede Position von T , ob an ihr ein Vorkommen von P beginnt. Dazu werden von links nach rechts die Zeichen von T mit den entsprechenden Zeichen von P verglichen. Tritt ein Mismatch auf, so liegt an der aktuellen Position kein Vorkommen von P vor und der Test wird abgebrochen. Stellt man dagegen fur¨ alle m Zeichen Ubereinstimmung¨ fest, so wurde ein Vorkommen gefunden. In beiden F¨allen verschiebt“ man P um eine Stelle und ” beginnt den Test an der n¨achsten Position.

Algorithmus 1.1 Naiver Algorithmus zur Wortsuche Eingabe: W¨orter P , T mit |P | = m, |T | = n Ausgabe: Menge S der Vorkommen von P in T (1) S ← ∅; (2) for k ← 1 to n − m + 1 (3) i ← 1; j ← k; (4) while i ≤ m and P [i] = T [j] (5) i ← i + 1; j ← j + 1; (6) if i = m + 1 then S ← S ∪ {k};

Die Korrektheit des naiven Algorithmus ist evident. Die Zahl der erforderlichen Vergleiche kann durch m · (n − m + 1) = O(m · n) abgesch¨atzt werden. Diese Schranke wird fur¨ P = am,

8 T = an auch erreicht. Im durchschnittlichen Fall ist das Verhalten des naiven Algorithmus sehr viel besser. Wir bestimmen dazu Comp(m), die mittlere Zahl der Vergleiche bis zum ersten Mismatch fur¨ zwei W¨orter der L¨ange m.Fur¨ 0 ≤ i ≤ m sei pi die Wahrscheinlichkeit, daß genau die ersten i Zeichen ubereinstimmen.¨ Dann gilt

m−1 X Comp(m) = pi · (i + 1) + pm · m. i=0

1 Fur¨ jeden Vergleich ist die Wahrscheinlichkeit eines Matches σ und die eines Mismatches 1 1 − σ . Damit ergibt sich 1  1  1 p = · 1 − fur¨ 0 ≤ i ≤ m − 1, p = i σi σ m σm und folglich

m−1 X 1  1  1 Comp(m) = · 1 − · (i + 1) + · m σi σ σm i=0 m−1 m−1 X 1 X 1 1 = · (i + 1) − · (i + 1) + · m σi σi+1 σm i=0 i=0 m−1 m X 1 X 1 1 = · (i + 1) − · i + · m σi σi σm i=0 i=1 m−1 X 1 1 1 = − · m + · m σi σm σm i=0 1 − σm = 1 1 − σ σ < σ − 1 Die durchschnittliche Zahl der Vergleiche bei der Suche in einem Text der L¨ange n betr¨agt σ (n − m + 1)Comp(m), also rund (n − m + 1) · σ−1 . Damit ist der naive Algorithmus fur¨ Texte in naturlichen¨ Sprachen akzeptabel und wird wegen der einfachen Implementierbarkeit auch oft genutzt. Im Falle l¨angerer Suchw¨orter ist jedoch der Boyer-Moore-Algorithmus, siehe Abschnitt 1.5, vorzuziehen.

1.2 R¨ander und Perioden

Beim naiven Algorithmus wurde das Suchwort vor der Suche nicht betrachtet. Unbefriedigen- de Laufzeiten kommen dann zustande, wenn das Suchwort eine bestimmte Struktur aufweist (hohe Periodizit¨at). Um bessere Ergebnisse als beim naiven Algorithmus zu erhalten, ist eine Vorverarbeitung (Pr¨aprozessing) des Suchwortes n¨otig. Bevor wir uns den einzelnen Algorith- men zuwenden, wollen wir einige Betrachtungen zu Regelm¨aßigkeiten in W¨ortern vornehmen, die beim Pr¨aprozessing genutzt werden.

9 Definition 1.1 Es sei P ein Wort. Ist α echtes Pr¨afix und echtes Suffix von P , so nennt man α einen Rand von P . Die L¨ange des l¨angsten Randes von P wird mit Border(P ) bezeichnet.

Definition 1.2 Es sei P ein Wort der L¨ange m. Eine Zahl p mit 1 ≤ p ≤ m heißt Periode von P , wenn P [i] = P [i + p] fur¨ alle 1 ≤ i ≤ m − p gilt. Die L¨ange der kurzesten¨ Periode von P wird mit Per(P ) bezeichnet.

Zwischen R¨andern und Perioden besteht folgender Zusammenhang, der unmittelbar aus den Definitionen folgt.

Lemma 1.1 Es sei P ein Wort der L¨ange m. Eine Zahl p, 1 ≤ p ≤ m, ist genau dann eine Periode von P , wenn P einen Rand der L¨ange (m − p) besitzt. In einem engen Zusammenhang zu den Perioden von P stehen auch die sogenannten Z- Werte.

Definition 1.3 Es sei P ein Wort der L¨ange m.Fur¨ 2 ≤ i ≤ m sei Zi(P ) die L¨ange des l¨angsten Pr¨afixes von P , das Pr¨afix von P [i . . . m] ist.

i 2 3 4 5 6 7 8 Beispiel 1.1 Fur¨ P = abaaabab ergibt sich Zi 0 1 1 3 0 2 0

Satz 1.2 Es sei P ein Wort der L¨ange m. Eine Zahl p, 1 ≤ p < m, ist genau dann eine Periode von P , wenn p + Zp+1(P ) = m gilt. Ist p keine Periode, so gilt P [1 + Zp+1(P )] 6= P [p + 1 + Zp+1(P )].

Beispiel 1.2 Fur¨ P = abaab ist 3 eine Periode; 2 ist keine Periode, und es gilt Z3(P ) = 1, d.h. P [2] 6= P [4].

a b a a b a b a a b a b a a b a b a a b

Zur Vereinfachung der Notation schreiben wir Zi statt Zi(P ), sofern klar ist, um welches Wort P es geht. Der gleichen Konvention folgen wir auch fur¨ andere von W¨ortern abh¨angigen Faktoren. Unser n¨achstes Ziel ist die Berechnung der Perioden in Linearzeit. Dafur¨ ist es offenbar ausreichend, alle Z-Werte in Linearzeit bezuglich¨ der Wortl¨ange zu berechnen, was durch den Z-Algorithmus (Algorithmus 1.2) geschieht. Der Z-Algorithmus berechnet fur¨ ein Wort P der L¨ange m nacheinander die Werte Z1,Z2, . . . , m, wobei fur¨ die Ermittlung eines Wertes Zk die bereits berechneten Z-Werte benutzt werden. Fur¨ ein Wort P der L¨ange m und 2 ≤ k ≤ m seien   rk(P ) := max {j + Zj(P ) − 1 : 1 < j < k} ∪ {k − 1} ,   `k(P ) := max {j : j + Zj(P ) − 1 = rk(P ) ∧ 1 < j < k} ∪ {k − 1} .

Das heißt, unter allen Intervallen [j, j + Zj − 1], die k enthalten, nehmen wir jenes, das am weitesten rechts endet. Sein rechter Rand ist rk, sein linker Rand ist `k. Sollte ein solches Intervall nicht existieren, so gilt `k = rk = k − 1.

10 Ist k > rk, so ermittelt man Zk durch zeichenweisen Vergleich ab den Stellen 1 bzw. k. Außerdem ergibt sich `k+1 = k sowie rk+1 = max{k + Zk − 1, k}.

Gilt hingegen k ≤ rk, so folgt aus den Definitionen P [`k . . . rk] = P [1 ...Z`k ] und damit 0 0 P [k . . . rk] = P [k ...Z`k ] fur¨ k = k − `k + 1.

P 1 a b c P 0 1 k Z`k P `k k rk

0 0 0 0 0 0 Gilt Zk ≤ Zjk − k , d.h. Zk ≤ r − k (im Bild Fall a), so folgt P [k + Zk ] = P [k + Zk ] 6= P [1 + Zk0 ] und damit Zk = Zk0 sowie rk+1 = rk und `k+1 = `k. Anderenfalls (im Bild F¨alle b bzw. c) gilt Zk ≥ r − k + 1 sowie rk+1 = k + Zk − 1 und `k+1 = k. In jedem Fall sind zur Berechnung von Zk keine Vergleiche zwischen P [1 . . . rk − k + 1] und P [k . . . rk] n¨otig.

Algorithmus 1.2 Z-Algorithmus Eingabe: Wort P , |P | = m Ausgabe: Zk(P ), 2 ≤ k ≤ m (1) ` ← 1; r ← 1; (2) for k ← 2 to m (3) if k ≤ r and Zk−`+1 ≤ r − k then Zk ← Zk−`+1; (4) else (5) ` ← k; i ← r − k + 2; (6) while r < m and P (r + 1) = P (i) (7) r ← r + 1; i ← i + 1; (8) Zk ← r − k + 1; (9) if r < k then r ← k;

Satz 1.3 Der Z-Algorithmus berechnet fur¨ ein Wort P der L¨ange m die Werte Zk(P ), 2 ≤ k ≤ m mit einem Aufwand von O(m). Beweis. Zum Beweis der Korrektheit zeigen wir durch Induktion: Vor jedem Durchlauf der for-Schleife gilt r = rk, ` = `k, und alle Werte Zj mit 2 ≤ j < k sind korrekt. IA: Fur¨ k = 2 ist die Behauptung wegen der Initialisierung von ` und r korrekt.

IS: Daß fur¨ jedes k nach dem Durchlauf der Schleife der Wert Zk korrekt berechnet ist und ` = `k+1, r = rk+1 gilt, folgt aus unseren Vorbetrachtungen. Die Laufzeit ist proportional zur Zahl der expliziten Vergleiche, die sich wiederum in Matches und Mismatches unterteilen lassen. Da fur¨ jedes k bei der Bestimmung von Zk h¨ochstens ein Mismatch auftritt, ist die Zahl der Mismatches durch m − 1 beschr¨ankt. Da jedes Match den Wert von r um 1 vergr¨oßert und ein Vergleich an der aktuellen Stelle r + 1 stattfindet, l¨aßt sich auch die Zahl der Matches ebenfalls durch m − 1 beschr¨anken. 2

Folgerung 1.4 Es sei P ein Wort der L¨ange m. Dann k¨onnen die Perioden von P mit einem Aufwand von O(m) ermittelt werden.

11 1.3 Der Algorithmus von Knuth-Morris-Pratt

Der Morris-Pratt-Algorithmus und der davon abgeleitete Algorithmus von Knuth, Morris und Pratt haben die gleiche Grundidee wie der naive Algorithmus: Das Suchwort P wird von links nach rechts uber¨ den Text T geschoben. In einer Phase wird P von links nach rechts mit den Zeichen von T ab einer Stelle j verglichen und bei Auftreten eines Mismatches bzw. bei Erreichen des Endes von P nach rechts verschoben. Der Unterschied zum naiven Algorithmus ist, daß Informationen zu Ubereinstimmungen¨ zwischen T ab einer Stelle k und Pr¨afixen von P ausgenutzt werden. Dadurch k¨onnen die Verschiebungen zwischen den Phasen gr¨oßer als 1 sein und Vergleiche, die garantiert mit einem Match enden, weggelassen werden. Ausgenutzt wird dabei die folgende Eignschaft von Perioden:

Lemma 1.5 Tritt ein Wort u im Text T an der Stelle k auf, so kann das n¨achste Vorkommen von u fruhstens¨ an der Stelle k0 = k + Per(u) auftreten. Das Vorkommen des Pr¨afixes der L¨ange Border(u) an der Stelle k0 ist dabei bereits garantiert.

Beweis. Es sei |u| = i. Gilt 1 ≤ p < Per(u), so ist p + Zp+1(u) < i, und es gilt T [k + p + Zp+1(u)] = u[1 + p + Zp+1(u)] 6= u[1 + Zp+1(u)], d.h., u kann nicht an der Stelle k + p vorkommen. Außerdem gilt T [k0 . . . k0 + Border(u) − 1] = T [k . . . k + Rand(u) − 1] = u[1 ... Border(u)] nach Definition der Periode. 2

Definition 1.4 Fur¨ 1 ≤ i ≤ |P | seien Border i(P ) bzw. Per i(P ) die L¨ange des l¨angsten Randes bzw. der kurzesten¨ Periode von P [1 . . . i]. Wir setzen Border 0(P ) := 0 und Per 0(P ) := 1.

Fur¨ die Wortsuche hat das Lemma folgende Auswirkung: Stimmen die ersten i Zeichen von P und T uberein,¨ so darf man P um Per i(P ) Felder verschieben und kann die ersten Border i(P ) Vergleiche auslassen. Dabei bedeutet “Verschiebung” eine Zuweisung der Form k ← k + Per i(P ); sie kann also in konstanter Zeit ausgefuhrt¨ werden.

Beispiel 1.3 Fur¨ P = abcabba erhalten wir folgende Werte fur¨ Border i und Per i. i 0 1 2 3 4 5 6 7 Border i 0 0 0 0 1 2 0 1 Per i 1 1 2 3 3 3 6 6 Wurde fur¨ P eine Ubereinstimmung¨ der L¨ange 5 an der Textstelle k gefunden, so darf man P um Per 5(P ) = 3 Stellen verschieben und die ersten Border 5 = 2 Vergleiche auslassen.

- a b c a b b a P a b c a b b a P ******* a b c a b **************** T k j

12 Algorithmus 1.3 Morris-Pratt-Algorithmus Eingabe: W¨orter P , T mit |P | = m, |T | = n (Die Werte Border i und Per i fur¨ P sind bekannt) Ausgabe: Menge S der Vorkommen von P in T (1) S ← ∅; k ← 1; i ← 1; j ← k; (2) while k ≤ n − m + 1 (3) while i ≤ m and P [i] = T [j] (4) i ← i + 1; j ← j + 1; (5) if i = m + 1 then S ← S ∪ {k}; (6) k ← k + Per i−1; (7) j ← k + Border i−1(P ); (8) i ← j − k + 1;

Satz 1.6 Der Morris-Pratt-Algorithmus findet alle Vorkommen von P in T mit einer Laufzeit von O(n). Beweis. Zum Beweis der Korrektheit zeigen wir durch Induktion: Bei jedem Aufruf von Zeile 2 sind alle Vorkommen von P vor der Stelle k gefunden, T [k . . . j− 1] stimmt mit P [1 . . . j − k] uberein¨ und i hat den Wert j − k + 1. Vor dem 1. Aufruf ist wegen k = j = 1 die Behauptung offensichtlich korrekt. Sei nun die Behauptung bei einem Aufruf erfullt.¨ Dann gilt nach dem Verlassen der inneren Schleife (Zeilen 3–4):

T [k . . . k + i − 2] = P [1 . . . i − 1] ∧ (T [k + i − 1] 6= P [i] ∨ i = m + 1).

Ein Vorkommen an der Stelle k existiert genau dann, wenn i = m+1 gilt, so daß die bedingte Zuweisung in Zeile 5 korrekt ist. Weiterhin gibt es keine Vorkommen hinter Position k und vor Position k + Per i, und T stimmt ab der Stelle k + Per i mit den ersten Border i Stellen von P uberein.¨ Nach den Zuweisungen fur¨ k, j, i folgt damit die Korrektheit der Induktions- behauptung in der n¨achsten Phase. Die Laufzeit des Algorithmus ist proportional zur Anzahl der Tests der Bedingung in Zeile 3. Nach einem positiven Test wird der Wert von j erh¨oht (Zeile 4), nach einem negativen der Wert von k (Zeile 6). Da die Werte von j und k niemals verringert werden und k ≤ n − m + 1 sowie j ≤ k + m − 1 gilt, ist die Zahl der Vergleiche beschr¨ankt durch 2n. 2

MP-Pr¨aprozessing

N¨achstes Ziel ist die Bestimmung der Border i-Werte in linearer Zeit bezuglich¨ |P |. Dies ist m¨oglich, indem man fur¨ die Berechnung von Border i die Werte Border 1,..., Border i−1 her- anzieht. Wir machen folgende Beobachtung: Es sei P [i + 1] = x, α der l¨angste Rand von P [1 . . . i] und β der l¨angste Rand von P [1 . . . i + 1]. Ist nun P [|α| + 1] = x, so ist β = αx, anderenfalls ist β der l¨angste Rand von αx. Durch Rekursion ergibt sich der Algorithmus MP-Pr¨aprozessing.

13 Algorithmus 1.4 MP-Pr¨aprozessing Eingabe: Wort P mit |P | = m Ausgabe: Border i(P ) fur¨ 0 ≤ i ≤ m (1) Border 0 ← 0; Border 1 ← 0; (2) for i ← 2 to m (3) t ← Border i−1; (4) while P [i] 6= P [t + 1] and t > 0 (5) t ← Border t; (6) if P [i] 6= P [t + 1] then Border i ← 0; (7) else Border i ← t + 1;

Lemma 1.7 Algorithmus 1.4 ermittelt die Border-Werte von P in einer Zeit von O(m). Beweis. Die Korrektheit des Algorithmus folgt aus der obigen Beobachtung. Die Laufzeit ist proportional zur Zahl der Tests der Schleifenbedingung in Zeile 4. Fur¨ ein festes i kann dieser Wert durch ti,0 − ti,1 + 1 abgesch¨atzt werden, wobei ti,0 bzw. ti,1 der Wert von t vor Betreten bzw. nach Verlassen der while-Schleife ist. Wegen ti,0 = Border i−1 und ti,1 ≥ Border i − 1 ergeben sich fur¨ ein festes i h¨ochstens Border i−1 − Border i + 2 Tests. Die Gesamtzahl der Tests wird abgesch¨atzt durch:

m X (Border i−1 − Border i + 2) = 2(m − 1) + Border 1 − Border m ≤ 2(m − 1). i=2 2

Graphische Interpretation Der Morris-Pratt-Algorithmus kann wie folgt graphisch interpretiert werden. Fur¨ ein Wort P der L¨ange m konstruieren wir einen Graphen mit den Knoten 0, 1, . . . , m.Fur¨ 1 ≤ i ≤ m gibt es die beschriftete Vorw¨artskante (i − 1,P [i], i) und die unbeschriftete Ruckw¨ ¨artskante von i nach Border i. (auch failure link genannt). Die Suche beginnt im Knoten 0. Ist die Vorw¨artskante aus dem aktuellen Knoten mit dem aktuellen Textzeichen beschriftet, so folgt man dieser Kante und betrachtet dann das n¨achste Textzeichen. Anderenfalls folgt man der Ruckw¨ ¨artskante und versucht es erneut mit dem aktuellen Textzeichen. Kann man vom Knoten 0 aus nicht dem aktuellen Textzeichen folgen, so verbleibt man im Knoten 0 und nimmt das n¨achste Textzeichen. Erreicht man den Knoten m, so wurde ein Vorkommen gefunden.

Beispiel 1.4 Fur¨ P = abcabba ergibt sich der folgende Graph:

? - a- b- c- a- b- b- a- 0 1 2 3 4 5 6 7 m6 m m6 m m m m m 

14 Verbesserung von Knuth Der Morris-Pratt-Algorithmus wird durch folgende Beobachtung zum Knuth-Morris-Pratt- Algorithmus verfeinert: Ist Per i(P ) auch eine Periode von P [1 . . . i + 1] und gibt es ein Mis- match zwischen der Textstelle j und P [i + 1], so gibt es nach der Verschiebung um Per i(P ) ein Mismatch zwischen der Textstelle j und P [Border i(P ) + 1]. Man darf also in den obigen Betrachtungen Per i(P ) durch SPer i(P ) ersetzen, wobei SPer i(P ) die L¨ange der kurzesten¨ Periode von P [1 . . . i] ist, die keine Periode von P [1 . . . i+1] ist. (Falls eine solche Periode nicht existiert, setzen wir SPer i(P ) = i. Die Knuth-Morris-Pratt- Verschiebung betr¨agt damit SPer i(P ). Außerdem setzen wir SBorder i(P ) = i − SPer i(P ).

Beispiel 1.5 Fur¨ P = abcabba gilt Per 4(P ) = 3 und SPer 4(P ) = 4. Tritt das erste Mismatch an der 5. Stelle auf, so betr¨agt die MP-Verschiebung 3, die KMP-Verschiebung 4. n Fur¨ P = a gilt SPer i(P ) = 1 und SBorder i(P ) = i.Fur¨ alle i betr¨agt die MP-Verschiebung 1, die KMP-Verschiebung i.

Die Werte SBorder i und SPer i sind ebenfalls in linearer Zeit berechenbar. Der KMP- Algorithmus ben¨otigt fur¨ jede Eingabe h¨ochstens so viele Vergleiche wie der MP-Algorithmus, im schlechtesten Falle (P = ab, T = an) allerdings ebenfalls 2n − 2. Ein großer Unterschied besteht bezuglich¨ der Verz¨ogerung (delay); das ist die maximale Anzahl von Vergleichen eines Textzeichens minus 1. W¨ahrend die maximale Verz¨ogerung beim MP-Algorithmus m − 1 be- tragen kann (P = am, T = am−1bam), ist sie fur¨ den KMP-Algorithmus in der Gr¨oßenordnung Θ(log m).

1.4 Suche mit deterministischen endlichen Automaten

Im engen Zusammenhang zum Algorithmus von Knuth-Morris-Pratt steht die Suche mit einem endlichen Automaten. Um die Vorkommen von P zu finden, konstruiert man den minimalen deterministischen endlichen Automaten (DEA), der die Sprache Σ∗P akzeptiert. Erreicht dieser DEA einen Endzustand, so wurde ein Vorkommen von P gefunden. Gilt P = x1x2 ··· xm mit x1, x2, . . . , xm ∈ Σ, so hat der DEA die folgende Gestalt:

AP = (Σ, {0, 1, . . . , m}, δ, 0, {m}) mit  i + 1 , falls 0 ≤ i < m, x = x δ(i, x) = i+1 . Border(x1 ··· xix), sonst

Beispiel 1.6 Fur¨ P = abcabba ergibt sich der folgende DEA (Kanten zum Zustand 0 wurden weggelassen):

a a a a ? - a- b- c- a- b- b- a- 0 1 2 3 4 5 6 7 m m6 m6 m6 mc m m m a b ¦ ¥ ∗ Satz 1.8 Es sei |Σ| = σ und P ∈ Σ ein Wort der L¨ange m. Der Automat AP kann mit einem Aufwand von O(m · σ) konstruiert werden.

15 Beweis. Es sei P = x1x2 ··· xm. Offensichtlich gilt  i + 1 , falls x = x δ(i, x) = i+1 δ(SBorder i, x), sonst.

Die Werte SBorder i sind mit einem Aufwand von O(m) berechenbar. Anschließend kann man fur¨ jeden Knoten i die Werte der Uberf¨ uhrungsfunktion¨ mit einem Aufwand von O(σ) bestimmen. 2

Algorithmus 1.5 DEA-Algorithmus zur Wortsuche Eingabe: W¨orter P , T uber¨ Σ mit |P | = m, |T | = n Ausgabe: Menge S der Vorkommen von P in T (1) Konstruiere den DEA AP = (Σ, {0, 1, . . . , m}, δ, 0, {m}); (2) S ← ∅; z ← 0; (3) for j ← 1 to n (4) z ← δ(z, T [j]); (5) if z = m then S ← S ∪ {j − m + 1};

Satz 1.9 Algorithmus 1.5 findet alle Vorkommen von P in T mit einer Laufzeit von O(n) (ohne Konstruktion von AP ). Beweis. Fur¨ die Korrektheit zeigt man per Induktion uber¨ k, daß δ(0,T [1 . . . k]) die L¨ange des l¨angsten Suffixes von T ist, das Pr¨afix von P ist. Die Laufzeitabsch¨atzung ist trivial. 2 Der Vorteil des DEA-Algorithmus gegenuber¨ dem KMP-Algorithmus ist, daß er ein soge- nannter Realtime-Algorithmus ist, d.h. eine Verz¨ogerung von 0 besitzt. Der Nachteil ist, daß der Automat einen Speicherplatz von O(m · σ) ben¨otigt, w¨ahrend fur¨ die SBorder-Werte ein Speicherplatz von O(m) genugt.¨

Variante von Simon Eine genauere Betrachtung des Automaten A zeigt, daß die meisten Ruckw¨ ¨artskanten“ im P ” Graphen des Automaten zum Zustand 0 fuhren.¨ Im folgenden bezeichnen wir eine Kante der Form (k, x, k + 1) als Vorw¨artskante, eine Kante der Form (k, x, j + 1) mit 0 ≤ j < k als Ruckw¨ ¨artskante und eine Kante der Form (k, x, 0) als triviale Kante.

∗ Lemma 1.10 Es sei P ∈ Σ ein Wort der L¨ange m. Der Graph des Automaten AP enth¨alt h¨ochstens m Ruckw¨ ¨artskanten. Beweis. Ist (k, x, j +1) eine Ruckw¨ ¨artskante, so gilt P [1 . . . j] = P [k−j +1 . . . k], P [j +1] = x sowie P [j + 1] 6= P [k + 1] oder k = m. Das heißt, fur¨ i = k − j + 1 erhalten wir Zi = j und k = i + Zi − 1. Damit hat jede Ruckw¨ ¨artskante die Form (i + Zi − 1,P [Zi + 1],Zi + 1), und es kann h¨ochstens m Ruckw¨ ¨artskanten geben. 2

Bei der Konstruktion von AP kann man nun die trivialen Kanten weglassen. Dies ist in Beispiel 1.6 bereits geschehen. Die Zeit fur¨ die Konstruktion von AP ist ebenfalls in O(n). Die Suche erfolgt wie mit dem Automaten AP selbst, also durch Bestimmung des Nachfol- gezustands. Da nicht mehr alle Kanten explizit gespeichert werden, muß man nun nach einer Ruckw¨ ¨artskante (k, x, j) suchen, was zu Verz¨ogerungen fuhrt.¨

16 Die maximale Verz¨ogerung an einer Textstelle ist abh¨angig von der Implementation. Spei- chert man fur¨ jeden Knoten die Ruckw¨ ¨artskanten als eine Liste, so betr¨agt sie σ.W¨ahlt man dabei die Reihenfolge in der Liste so, daß die Kanten in absteigender Ordnung des Zielknotens geordnet sind, so braucht man h¨ochstens so viele Schritte wie beim KMP-Algorithmus. Speichert man die Kanten als (entsprechend der lexikografischen Ordnung der Beschrif- tung) geordnetes Array, so kann man bin¨are Suche anwenden und erh¨alt eine maximale Verz¨ogerung log2 σ. Wir wollen als n¨achstes zeigen, daß fur¨ beide Implementierungen, wie uberhaupt¨ fur¨ jede “vernunftige”¨ Implementierung, die Gesamtlaufzeit linear (unabh¨angig von σ) ist.

Lemma 1.11 Es sei P ∈ Σ∗ ein Wort der L¨ange m. Gehen von einem Knoten k im Graphen von AP r Ruckw¨ ¨artskanten aus, so gilt fur¨ jede Ruckw¨ ¨artskante (k, x, j + 1): k − j ≥ r.

Beweis. Nach der Definition von AP gibt es in P [1 . . . k] einen Rand der L¨ange j, d.h. k − j ist eine Periode von P [1 . . . k]. Dann muß aber jedes Teilwort von P [1 . . . k] der L¨ange k − j alle in P [1 . . . k] vorkommenden Symbole enthalten. Da P [1 . . . k] mindestens r verschiedene Symbole enth¨alt, folgt k − j ≥ r. 2

Satz 1.12 Es seien P,T ∈ Σ∗ mit |P | = m, |T | = n. Jede Implementierung des Simon- Algorithmus, die eine Vorw¨artskante in einem Schritt und eine Ruckw¨ ¨artskante bzw. triviale Kante von einem Knoten mit r Ruckw¨ ¨artskanten in h¨ochstens r + 1 Schritten findet, findet die Vorkommen von P in T in h¨ochstens 2n Schritten. Beweis. Ist (k, x, j) eine Ruckw¨ ¨artskante oder eine triviale Kante, so bezeichnen wir k −j als die L¨ange dieser Kante. Hat eine Ruckw¨ ¨artskante oder triviale Kante (k, x, j) die L¨ange r, so gehen nach Lemma 1.11 von k h¨ochstens r + 1 Ruckw¨ ¨artskanten aus; nach der Voraussetzung des Satzes wird (k, x, j) in h¨ochstens r + 2 Schritten gefunden. Fur¨ jedes Zeichen des Textes geht man inm Graphen eine Kante. Benutzt man eine Ruckw¨ ¨artskante oder triviale Kante der L¨ange r, mussen¨ zuvor mindestens r Vorw¨artskanten verwendet worden sein. Fur¨ diese r +1 Kanten sind h¨ochstens 2r +2 Schritte erforderlich. Fur¨ das Finden einer Ruckw¨ ¨artskante der L¨ange 0 ben¨otigt man h¨ochstens 2 Schritte. Insgesamt werden fur¨ die Bestimmung der n Kanten h¨ochstens 2n Schritte ben¨otigt. 2

1.5 Boyer-Moore-Algorithmus

Der Algorithmus Wie bisher wird das Suchwort P von links nach rechts uber¨ den Text geschoben. Der zei- chenweise Vergleich in einer Phase erfolgt jedoch von rechts nach links. Wird ein Mismatch entdeckt oder das linke Ende von P erreicht, erfolgt eine Verschiebung nach rechts, wobei kein Vorkommen von P ubergangen¨ wird. Die Verschiebung wird nach den beiden folgenden Regeln ermittelt.

Bad Character Regel. Findet man beim ersten Vergleich das Textsymbol x, so darf man P so weit verschieben, daß das rechteste Vorkommen von x in P auf diese Textposition trifft.

17 - x P x y P x T

Good Suffix Regel. Stimmt ein Suffix α von P mit dem aktuellen Text uberein,¨ so darf man P so weit verschieben, daß das letze Vorkommen von α in P 0 = P [1 . . . m − 1] gegenuber¨ dem entsprechenden Text steht.

- α P α α P α T Sollte ein solches Vorkommen nicht existieren, so darf man P so weit verschieben, daß das l¨angste Suffix von α, das ein Pr¨afix von P 0 ist, gegenuber¨ dem Ende des aktuellen Textstuckes¨ steht.

- β P β α β P α β T

Formal fuhren¨ wir zur Beschreibung der beiden Heuristiken die folgenden Gr¨oßen ein.

Definition 1.5 Fur¨ P ∈ Σ∗ mit |P | = m und x ∈ Σ ist

Rx(P ) := max ({1 ≤ i < m : P [i] = x} ∪ {0}) , d.h., Rx(P ) ist das letzte Vorkommen von x in P vor der letzten Stelle von P .

Definition 1.6 Sei P ∈ Σ∗ mit |P | = m.Fur¨ 1 ≤ i ≤ m sei  Li(P ) := max {j : m − i + 1 ≤ j < m ∧ P [i . . . m] = P [j + i − m . . . j]} ∪  {j : 0 ≤ j ≤ m − i ∧ P [m − j + 1 . . . m] = P [1 . . . j]}

`i(P ) := max{j : 0 ≤ j ≤ m − i ∧ P [m − j + 1 . . . m] = P [1 . . . j]}, d.h. `i ist die L¨ange des l¨angsten echten Suffixes von P [i . . . m], das Pr¨afix von P ist, und Li ist die letzte Position, an der in P [1 . . . m − 1] ein Vorkommen von P [i . . . m] endet, bzw. `i, falls ein solches Vorkommen nicht existiert. Gemeinsam ergeben die beiden Heuristiken die Boyer-Moore-Verschiebungsregel:

Es sei i die erste Stelle von rechts in P , bei der ein Mismatch auftritt. Gilt i = m, so verschiebe um m − Rx(P ). Anderenfalls verschiebe um m − Li(P ).

18 Beispiel 1.7 Fur¨ P = ababcbab mit Σ = {a, b, c, d} ergibt sich:

x a b c d i 1 2 3 4 5 6 7 8 Rx 7 6 5 0 Li 2 2 2 2 2 4 4 6 Dies fuhrt¨ zu folgenden Verschiebungen.

Suchwort: ababcbab ababcbab ababcbab Textausschnitt: ...... d...... aab.. .cabcbab... Verschiebung: 8 4 6

Algorithmus 1.6 Boyer-Moore-Algorithmus Eingabe: W¨orter P , T mit |P | = m, |T | = n (Die Werte Rx und Li fur¨ P sind bekannt) Ausgabe: Menge S der Vorkommen von P in T (1) S ← ∅; k ← m; (2) while k ≤ n (3) i ← m; j ← k; x ← T [k]; (4) while i ≥ 1 and P [i] = T [j] (5) i ← i − 1; j ← j − 1; (6) if i = 0 then S ← S ∪ {k − m + 1}; (7) if i = m then k ← k + m − Rx; (8) else k ← k + m − Li+1;

Satz 1.13 Der Boyer-Moore-Algorithmus findet alle Vorkommen von P in T . Beweis. Es ist zu zeigen, daß bei den Verschiebungen keine Vorkommen von P ubersprungen¨ werden. Ein formaler Beweis dieser Tatsache erfolgt analog zum Korrektheitsbeweis des KMP- Algorithmus (Satz 1.6). 2

Boyer-Moore-Pr¨aprozessing in Linearzeit

Die fur¨ die Verschiebung nach der Bad Character Regel ben¨otigten Werte Rx(P ) k¨onnen sehr einfach mit einem Aufwand von O(m + σ) bestimmt werden:

Algorithmus 1.7 BM-Pr¨aprozessing: Rx-Werte Eingabe: Wort P ∈ Σ∗, |P | = m Ausgabe: Rx(P ) fur¨ x ∈ Σ (1) foreach x ∈ Σ (2) Rx ← 0; (3) for i ← 1 to m − 1 (4) x ← P [i]; Rx ← i;

Zur Bestimmung der fur¨ die Good Suffix Regel ben¨otigten Li-Werte ermittelt man zunchst die `i-Werte. Offensichtlich ist `i(P ) die L¨ange des l¨angsten Randes von P , die nicht gr¨oßer als m − i ist.

19 Algorithmus 1.8 BM-Pr¨aprozessing: `i-Werte Eingabe: Wort P ∈ Σ∗, |P | = m Ausgabe: `i(P ) fur¨ 1 ≤ i ≤ m (1) Bestimme die R¨ander von P und speichere ihre L¨angen in fallender Reihenfolge als Stack L; (Das oberste Element von L ist Border(P ), das unterste ist 0.) (2) i ← 1; (3) while L nicht leer (4) ` ← Pop(L); (5) while ` ≤ m − i and i ≤ m (6) `i ← `; i ← i + 1;

Da man die R¨ander von P in linearer Zeit bestimmen kann, sind auch die `i-Werte in linearer Zeit ermittelbar. 0 Um noch die Li-Werte zu bestimmen, sucht man in P := P [1 . . . m − 1] von hinten nach 0 Vorkommen von Suffixen von P . Kommt ein Suffix P [i . . . m] nicht in P vor, so ist Li = `i; 0 kommt aber P [i . . . m] in P vor, so ist Li ≥ `i. Deshalb darf man zun¨achst Li ← `i setzen. Findet man bei der Suche von rechts nach links eine Ubereinstimmung¨ P [i . . . m] = P 0[k + i − m . . . k] und gilt zu diesem Zeitpunkt Li < k, so kann man Li ← k setzen. Um die Suche in Linearzeit zu erledigen, geht man ¨ahnlich wie beim KMP-Algorithmus vor. Insbesondere ben¨otigt man wieder die l¨angsten R¨ander, dieses Mal der Suffixe.

r Definition 1.7 Fur¨ 1 ≤ i ≤ |P | = m sei Border i (P ) die L¨ange des l¨angsten Randes von P [i . . . m]. r r r Offensichtlich gilt Border i (P ) = Border m−i+1(P ), d.h. die Border -Werte sind in Linear- r zeit berechenbar, und es gilt Border(P ) = Border 1(P ).

Algorithmus 1.9 BM-Pr¨aprozessing: Li-Werte Eingabe: Wort P ∈ Σ∗, |P | = m Ausgabe: Li(P ) fur¨ 1 ≤ i ≤ m r (1) Berechne Border i fur¨ 1 ≤ i ≤ m. (2) for i ← 1 to m (3) Li ← `i; (4) i ← m; k ← m − 1; j ← k; (5) while j > 0 (6) while j > 0 and P [i] = P [j] (7) if Li < k then Li ← k; (8) i ← i − 1; j ← j − 1; (9) if j = k then k ← j − 1; j ← k; i ← m; r r (10) else k ← j + Border i+1; i ← m − Border i+1;

Satz 1.14 Algorithmus 1.9 berechnet fur¨ ein Wort P der L¨ange m die Werte Li (1 ≤ i ≤ m) in einer Zeit von O(m). r Beweis. Die Border i -Werte sind in linearer Zeit berechenbar. Ansonsten werden die Kor- rektheit und die Komplexit¨at analog zum Morris-Pratt-Algorithmus gezeigt. 2

20 Laufzeit im schlechtesten Fall Der Algorithmus von Boyer-Moore ist in der Praxis sehr effizient. Fur¨ den bisher betrachteten Algorithmus ist die Laufzeit im schlechtesten Falle (P = am,T = an) jedoch Θ(mn). Man kann aber zeigen, daß der Boyer-Moore-Algorithmus in Linearzeit l¨auft, wenn P nicht in T vorkommt. Damit ergibt sich ein Algorithmus mit linearer Laufzeit auch im schlechtesten Fall, indem man folgende zus¨atzliche Regel (Regel von Galil) beachtet: Wurde ein Vorkommen von P in T gefunden, so prufe¨ in der n¨achsten Phase r r h¨ochstens die letzten m − Border 1(P ) Zeichen (da fur¨ die ersten Border 1(P ) Zei- chen die Ubereinstimmung¨ garantiert ist). Der Beweis fur¨ das obige Laufzeit-Resultat ist ziemlich schwierig. Man kann ihn im Buch von Gusfield [6] finden. Wir werden sp¨ater im Abschnitt 1.6 eine Variante des Boyer-Moore- Algorithmus betrachten, fur¨ die man relativ einfach eine lineare Laufzeit im schlechtesten Fall beweisen kann.

Durchschnittliche Laufzeit des Boyer-Moore-Algorithmus Wir beenden den Abschnitt mit einigen Uberlegungen¨ zur durchschnittlichen Laufzeit des Boyer-Moore-Algorithmus. Der Einfachheit halber betrachten wir eine auch als Horspool- Algorithmus bekannte Variante, bei der die Verschiebung immer nach der Bad Character Regel erfolgt. Wir m¨ochten die mittlere Laufzeit T (m, n) fur¨ Suchw¨orter der L¨ange m und Texte der L¨ange n ermitteln. Dazu bestimmen wir die mittlere Anzahl der Vergleiche Comp(m) sowie die mittlere Verschiebung Shift(m) fur¨ Suchw¨orter und Textabschnitte der L¨ange m.Fur¨ die n·Comp(m) mittlere Laufzeit gilt T (m, n) ≈ Shift(m) . Analog zu den Betrachtungen fur¨ den naiven Algorithmus (Abschnitt 1.1) erhalten wir σ Comp(m) ≤ σ−1 . Die mittlere Verschiebung ergibt sich als

m−1 X Shift(m) = pi · (i + 1), i=0 k wobei pi die Wahrscheinlichkeit dafur¨ ist, daß fur¨ ein x ∈ Σ und ein zuf¨alliges Wort P ∈ Σ , Rx(P ) = m − 1 − i ist. Offensichtlich gilt  1 i 1 p = 1 − · fur¨ 0 ≤ i ≤ m − 2, p = (1 − 1σ)m−1 , d.h. i σ σ m−1

m−2 i m−1 X  1  1  1  Shift(m) = 1 − · (i + 1) + 1 − · m σ σ σ i=0 m−2 X 1 = pi(1 − p) · (i + 1) + pm−1 · m mit p = 1 − . σ i=0 Analog zu den Betrachtungen fur¨ den naiven Algorithmus ergibt sich 1 − pm   1 m Shift(m) = = σ 1 − 1 − . 1 − p σ

21 Der Wert von Shift(m) ist abh¨angig vom Verh¨altnis zwischen Alphabetgr¨oße σ und Such- wortl¨ange m.Fur¨ m  σ betr¨agt er ungef¨ahr σ, w¨ahrend sich fur¨ σ  m in etwa der Wert m ergibt. Fur¨ σ = 100 erhalten wir beispielsweise:

m 2 10 50 100 200 1000 Shift(m) 1.99 9.6 39.5 63.4 86.6 99.996

Erweiterte Bad Character Regel Wie soeben gesehen, ist die mittlere Verschiebung durch die Alphabetgr¨oße σ beschr¨ankt. Eine Vergr¨oßerung der mittleren Verschiebung kann man erreichen, indem man die Bad Character Regel auf W¨orter einer festen L¨ange q erweitert. Zun¨achst ermittelt man fur¨ jedes Wort α der L¨ange q sein letztes Auftreten in P [1 . . . m − 1]. Man vergleicht in jeder Phase zun¨achst die letzten q Symbole des Suchwortes mit dem Text. Tritt dabei ein Mismatch auf und ist der Text α, so verschiebt man so weit, bis das von rechts n¨achste Vorkommen von α im Suchwort gegenuber¨ dem Text steht. Genauer definieren wir:

q ∗ Definition 1.8 Fur¨ q ≥ 1, α ∈ Σ , P ∈ Σ , |P | = m ≥ q sei Rα(P ) die rechteste Stelle in P 0 = P [1 . . . m − 1], an der ein Vorkommen von α endet oder die L¨ange des l¨angsten Suffixes von α, das Pr¨afix von P ist, falls α nicht in P 0 auftritt. Es ergibt sich die verallgemeinerte Bad Character Regel: Ergeben die q letzten aktuellen Textzeichen das Wort α, so verschiebe um den Betrag m − Rα(P ). Man stellt fest, daß die mittlere Zahl der Vergleiche pro Phase q + O(1) und die mittlere q Verschiebung Θ(min{σ , m}) betr¨agt. Das Pr¨aprozessing (Berechnung der Rα) erfordert einen Aufwand von O(m + σq). Man kann q naturlich¨ abh¨angig von m w¨ahlen. Die optimale Wahl ist q = logσ m. Die mittlere Zahl der Vergleiche pro Phase betr¨agt dann Comp(m) = Θ(logσ m), die mittlere Verschiebung ist Θ(m). Der Aufwand fur¨ das Pr¨aprozessing ist O(m). Die mittlere Laufzeit n·logσ m ist Θ( m ), was optimal ist.

1.6 Apostolico-Giancarlo-Algorithmus

Der Apostolico-Giancarlo-Algorithmus ist eine Variante des Boyer-Moore-Algorithmus, fur¨ die man relativ einfach eine lineare Laufzeit auch im schlechtesten Fall nachweisen kann. In dieser Variante werden die gleichen Verschiebungen wie beim Boyer-Moore-Algorithmus durchgefuhrt;¨ es werden jedoch einige Vergleiche eingespart. Dazu ist ein weiteres Pr¨aprozes- sing des Suchwortes P n¨otig, um die wie folgt definierten Werte Ni(P ) zu bestimmen.

Definition 1.9 Es sei P ein Wort der L¨ange m.Fur¨ 1 ≤ i ≤ m − 1 sei Ni(P ) die L¨ange des l¨angsten Suffixes von P , das Suffix von P [1 . . . i] ist.

i 1 2 3 4 5 6 7 Beispiel 1.8 Fur¨ P = ababcbab erh¨alt man Ni 0 2 0 3 0 1 0

r Offensichtlich gilt Ni(P ) = Zm−i+1(P ) fur¨ ein Wort der L¨ange m, d.h., die N-Werte k¨onnen in Linearzeit berechnet werden. Weiterhin wird jeder Stelle j des Textes ein Wert Mj zugeordnet, der mit 0 initialisiert ist. Wird im Laufe des Algorithmus die Stelle k als

22 Ende eines Vorkommens getestet, so wird Mk am Ende dieses Testes derart modifiziert, daß folgende Bedingungen erfullt¨ sind.

(*) P [m − Mk + 1 . . . m] = T [k − mk + 1 . . . k].

(**) Fur¨ alle k − Mk < j < k gilt j − Mj ≥ k − Mk. Wir betrachten einen Schritt des Algorithmus, bei dem fur¨ eine Position k in T getestet wird, ob hier ein Vorkommen von P endet, und in P bzw. T die Positionen i bzw. j er- reicht wurden. Gilt Mj = 0, so wird wie im Boyer-Moore-Algorithmus explizit der Vergleich ausgefuhrt.¨ Wie wir sp¨ater sehen werden, liegt j in diesem Fall außerhalb jedes Intervalles [` − M` + 1, `].

1. Gilt P [i] = T [j], so wird wie beim Boyer-Moore-Algorithmus die Phase fortgesetzt.

2. Gilt P [i] 6= T [j], so wird wie beim Boyer-Moore-Algorithmus die Phase beendet.

Gilt aber Mj > 0, so k¨onnen folgende F¨alle auftreten (die Teilw¨orter P [i − Ni + 1 . . . i] und T [j − Mj + 1 . . . j] sind in den Bildern jeweils hervorgehoben):

3. Ni ≥ Mj > 0:

P T

Es gilt P [i − Mj + 1 . . . i] = T [j − Mj + 1 . . . j]. Die n¨achsten Mj Vergleiche darf man auslassen, d.h., man verringert i und j um Mj.

4. Mj > Ni = i:

P T

Es gilt P [1 . . . i] = T [j − i + 1 . . . j], d.h. ein Vorkommen von P wurde gefunden.

5. Mj > Ni ∧ i > Ni:

P T

Es gilt P [i − Ni + 1 . . . i] = T [j − Ni + 1 . . . j] und P [i − Ni] 6= T [j − Ni], d.h. das erste Mismatch fur¨ die Position k besteht zwischen P [i − Ni] und T [j − Ni].

23 Algorithmus 1.10 Apostolico-Giancarlo-Algorithmus Eingabe: W¨orter P , T mit |P | = m, |T | = n (Die Werte Rx, Li und Ni fur¨ P sind bekannt) Ausgabe: Menge S der Vorkommen von P in T (1) Initialisiere Mj ← 0 fur¨ 1 ≤ j ≤ n; (2) S ← ∅; k ← m; (3) while k ≤ n (4) i ← m; j ← k; x ← T [k]; stop ← false ; (5) while i ≥ 1 and not stop (6) if Tj = 0 and P [i] = T [j] then i ← i − 1; j ← j − 1; (7) if Tj = 0 and P [i] 6= T [j] then stop ← true ; (8) if Tj 6= 0 and Ni ≥ Mj then i ← i − Mj; j ← j − Mj; (9) if Tj 6= 0 and Mj > Ni = i then i ← 0; (10) if Tj 6= 0 and Mj > Ni and i > Ni then i ← i − Ni; stop ← true ; (11) Mk ← k − j; if i = 0 then S ← S ∪ {k − m + 1}; (12) if i = m then k ← k + m − Rx; (13) else k ← k + m − Li+1;

Es bleibt zu zeigen, daß der Apostolico-Giancarlo-Algorithmus korrekt ist und eine linea- re Laufzeit hat. Wir bezeichnen den Test auf das Ende eines Vorkommens von P an einer Textstelle k (d.h. einen Durchlauf der ¨außeren while-Schleife) als eine Phase. Den Test fur¨ die Stellen P [i] und T [j] (d.h. einen Durchlauf der inneren while-Schleife) bezeichnen wir als einen Schritt. Wir beweisen zun¨achst das folgende technische Lemma.

Lemma 1.15 1. Vor und nach jedem Schritt gilt

(a) P [i + 1 . . . m] = T [k − m + i + 1 . . . k] und m − i ≥ k − j,

(b) j ≤ ` − M` fur¨ alle ` > j.

2. Zu jedem Zeitpunkt erfullen¨ die Werte von M1,M2,...,Mn die Bedingungen (*) und (**).

3. Am Ende jeder Phase gilt, vor der Erh¨ohung von k: P [i] 6= T [k − m + i] oder i = 0, d.h., i in P ist die erste Position von rechts, an der ein Mismatch auftritt. Beweis. Wir zeigen die Behauptungen durch Induktion. Vor dem Beginn der ersten Phase ist Behauptung 2 offenbar erfullt.¨ Sei nun Behauptung 2 zu Beginn einer beliebigen Phase erfullt.¨ Wegen i = m, j = k und M` = 0 fur¨ alle ` > k gilt zu diesem Zeitpunkt auch Behauptung 1. Behauptung 2 bleibt bis zur Anderung¨ von Mk am Ende der Phase gultig.¨ Sei nun Behauptung 1 vor einem Schritt erfullt.¨ Daß Behauptung 1a nach dem Schritt erfullt¨ ist, folgt aus unseren Betrachtungen zu den 5 verschiedenen F¨allen. Der Wert von j wird in den F¨allen 2, 4 und 3 nicht ver¨andert; in diesen F¨allen bleibt Behauptung 1b also gultig.¨ Im Fall 1 gilt vor dem Schritt Tj = 0 und damit j − 1 ≤ ` − M` fur¨ alle ` > j − 1. Im Fall 1 gilt vor dem Schritt j − Tj ≤ ` − T` fur¨ alle j − Tj ≤ ` ≤ j (wegen der Gultigkeit¨ von 2) und damit j − Tj ≤ ` − M` fur¨ alle ` > j − Tj. In beiden F¨allen ist Behauptung 1b nach dem Schritt gultig.¨

24 Am Ende der Phase wird Mk ← k − j gesetzt. Da Behauptung 1a gultig¨ ist, erfullt¨ Mk die Bedingung (*). Da Behauptung 1b gultig¨ ist, wird auch die Bedingung (**) erfullt.¨ Damit ist Behauptung 2 am Ende der Phase gultig.¨ Die Gultigkeit¨ von Behauptung 3 am Ende der Phase folgt wiederum aus den Vorbetrachtungen der 5 F¨alle. 2

Satz 1.16 Der Apostolico-Giancarlo-Algorithmus findet alle Vorkommen von P in T mit einer Laufzeit von O(m).

Beweis. Nach Lemma 1.15 bestimmt der Algorithmus in jeder Phase das l¨angste Suffix von P , das mit dem aktuellen Text ubereinstimmt.¨ Danach wird die Verschiebung wie beim Boyer- Moore-Algorithmus durchgefuhrt.¨ Die Korrektheit des Giancarlo-Apostolico-Algorithmus folgt aus der Korrektheit des Boyer-Moore-Algorithmus. Fur¨ die Absch¨atzung der Laufzeit z¨ahlen wir, wie oft die verschiedenen F¨alle fur¨ die einzelnen Schritte auftreten k¨onnen. Die F¨alle 2, 4, 5 beenden eine Phase und treten damit insgesamt h¨ochstens n-mal auf. Tritt Fall 1 an einer Stelle j < k auf, so gilt am Ende der Phase k − Mk ≤ j < k, d.h. j wird nach Behauptung 1b von Lemma 1.15 nie wieder erreicht. Tritt Fall 1 an einer Stelle j = k auf, so gilt am Ende der Phase Mj > 0, d.h. Fall 1 tritt an dieser Stelle nicht wieder auf. Tritt schließlich Fall 3 an einer Stelle j auf, so gilt j < k und am Ende der Phase k − Mk ≤ j < k, d.h. j wird nach Behauptung 1b von Lemma 1.15 nie wieder erreicht. Insgesamt treten also die F¨alle 1–5 h¨ochstens 3n-mal auf. 2 3 Eine genauere Analyse zeigt, daß h¨ochstens 2 n Schritte n¨otig sind. Außerdem ben¨otigt der Apostolico-Giancarlo-Algorithmus offensichtlich in jedem Fall h¨ochstens so viele Schritte wie der Boyer-Moore-Algorithmus (wobei ein Schritt des Apostolico-Giancarlo-Algorithmus naturlich¨ viel komplexer ist).

1.7 Algorithmus von Vishkin

Wir wollen jetzt einen weiteren Linearzeit-Algorithmus kennenlernen, der sich besonders gut parallelisieren und auf mehrdimensionale Mustersuche verallgemeinern l¨aßt. Bei diesem Al- gorithmus wird in der ersten Phase eine sogenannte Kandidatenmenge von Textpositionen ermittelt, in der alle Vorkommen von P sowie weitere Positionen enthalten sind. In der zwei- ten Phase wird fur¨ jeden Kandidaten durch zeichenweisen Vergleich ermittelt, ob tats¨achlich das Suchwort an dieser Stelle des Textes steht. Eine entscheidende Rolle spielen dabei der in Satz 1.2 genannte Zusammenhang zwischen Perioden und Z-Werten: Ist p keine Periode, so gilt P [1 + Zp+1(P )] 6= Z[p + 1 + Zp+1(P )]. Die Positionen 1 + Zp+1 und p + 1 + Zp+1 sind in diesem Falle Zeugen dafur,¨ daß P keine Periode ist.

Lemma 1.17 Es seien P und T W¨orter mit |P | = m, |T | = n.

1. Tritt P in T an den Stellen j und k mit 1 ≤ j < k ≤ n−m+1 auf, so ist k −j entweder gr¨oßer als m oder eine Periode von P .

2. Ist k−j eine Periode von P und kommt P an der Stelle j in T vor, so ist T [k . . . j+m−1] ein Pr¨afix von P .

3. Ist k − j eine Periode von P und gilt T [j + i − 1] 6= P [i] fur¨ ein i ∈ {k − j + 1, . . . , m}, so ist T [k . . . j + m − 1] kein Pr¨afix von P .

25 Beweis.

1. Aus T [j . . . j+m−1] = P und T [k . . . k+m−1] = P folgt T [k+i−1] = P [i+k−j] = P [i] fur¨ 1 ≤ i ≤ m − (k − j) und damit ist k − j eine Periode oder gr¨oßer als m.

2. Folgt aus der Definition der Periode.

3. Folgt aus der Definition der Periode.

2

Definition 1.10 Es sei P ein Wort mit |P | = m. Zwei naturliche¨ Zahlen j und k mit j < k heißen vertr¨aglich bezuglich¨ P , wenn es einen Text T gibt, der sowohl an der Stelle j als auch an der Stelle k ein Vorkommen von P enth¨alt.

Folgerung 1.18 Es sei P ein Wort mit |P | = m. Zwei Zahlen j und k mit j < k sind genau dann vertr¨aglich bezuglich¨ P , wenn k − j eine Periode von P oder gr¨oßer als m ist.

Lemma 1.19 Sind jeweils j1 < j2 und j2 < j3 vertr¨aglich bezuglich¨ P , so sind auch j1 und j3 vertr¨aglich bezuglich¨ P . Beweis. Zu zeigen ist, daß die Summe zweier Perioden eine Periode oder gr¨oßer als |P | ist. (Ubungsaufgabe)¨ 2 Sind j < k unvertr¨aglich und ist i = k − j, so kann man durch einen Vergleich von T [k + Zi+1] mit P [1 + Zi+1] eine der Positionen als Vorkommen von P ausschließen, da P [1+Zi+1] 6= P [1+Zi+1 +i] gilt und damit nur eine der Positionen {j, k} mit dem Symbol an der Stelle k + Zi+1 vereinbar ist. Dieses Ausschlußverfahren wird durch die folgende Prozedur Duell(j, k) realisiert.

Prozedur: Duell(j1, j2) Eingabe: W¨orter P , T , unvertr¨agliche Positionen j1 < j2 Ausgabe: nicht ausgeschlossene Position von {j1, j2} (1) i ← j2 − j1; (2) if T [j2 + Zi+1] = P [1 + Zi+1] then return j2; (3) else return j1;

Im Algorithmus von Vishkin wird in der ersten Phase eine Menge C von Kandidaten fur¨ ein Vorkommen von P in T ermittelt. Jedes Vorkommen ist in C enthalten, und alle Positionen in C sind paarweise vert¨aglich. Zur Ermittlung von C benutzt man einen Stack, in den man von rechts beginnend versucht, paarweise vertr¨agliche Kandidaten aufzunehmen. Wegen der Transitivit¨at der Vertr¨aglichkeit (Lemma 1.19) genugt¨ es sicherzustellen, daß eine neu aufgenommene Position mit der Spitze des Stacks vertr¨aglich ist. Solange die aktuelle Position j unvertr¨aglich mit der Stack-Spitze ist und das Duell gewinnt, wird die Stack-Spitze entfernt. Ist j am Ende mit der Stack-Spitze vertr¨aglich, so kann man j aufnehmen.

Beispiel 1.9 Es sei P = abcabcabcab. Die kurzeste¨ Periode von P ist 3. Die obersten Stack- positionen seien 20, 23, 29; die aktuelle Position 18.

26 ······ 18 20 23 29

Die Positionen 18 und 20 sind unvertr¨aglich; es gilt Z3(P ) = 0. Ist T [20] = a = P [1], so gewinnt die Position 20 das Duell, Position 18 scheidet aus. Anderenfalls scheidet Positi- on 20 aus. Da 18 und 23 ebenfalls unvertr¨aglich sind, mussen¨ sich diese beiden Positionen auch duellieren. Gewinnt Position 18 erneut, so wird sie die neue Stackspitze, da 18 und 29 vertr¨aglich sind.

Algorithmus 1.11 Algorithmus von Vishkin: 1. Phase Eingabe: W¨orter P ,T , |P | = m, |T | = n Ausgabe: Menge (Stack) C von Kandidaten fur¨ Vorkommen von P in T (1) C ← {n + 1}; (2) for j ← n − m + 1 downto 1 (3) while j und Top(C) unvertr¨aglich and Duell(j, Top(C)) = j (4) Pop(C); (5) if j und Top(C) vertr¨aglich then Push(C, j);

Satz 1.20 Nach dem Ablauf von Algorithmus 1.11 enth¨alt die Menge C alle Vorkommen von P in T , wobei die Positionen in C paarweise vertr¨aglich bezuglich¨ P sind. Die Laufzeit von Algorithmus 1.11 ist Θ(n).

Beweis. Die Korrektheit folgt aus den Betrachtungen zu vertr¨aglichen Positionen (Lemmata 1.17 und 1.19). Fur¨ die Laufzeit stellen wir fest, daß jede Position h¨ochstens einmal in einem Duell unterliegt. Die Zahl der Duelle ist damit durch n beschr¨ankt. 2 In der zweiten Phase wird fur¨ alle Positionen aus C getestet, ob tats¨achlich ein Vorkommen vorliegt. Gem¨aß der zweiten und dritten Aussage von Lemma 1.17 kann die Vergleichsphase wie folgt vereinfacht werden: Beginnt an der Stelle k ein Vorkommen von P , das an der Textstelle j endet, so braucht man fur¨ den n¨achsten Kandidaten die Vergleiche erst ab Stelle j + 1 vorzunehmen. Gibt es beim Vergleich an der Textstelle j dagegen ein Mismatch, so scheiden auch alle weiteren Kandidaten bis j aus.

Beispiel 1.10 Es sei P = abcabcabcab; k und j = k + 3 seien m¨ogliche Kandidaten. Stimmt T [k ··· k + 10] mit P uberein,¨ so gibt es auch eine Ubereinstimmung¨ von T [j ··· j + 7] mit P [1 ··· 8]. Gibt es dagegen ein Mismatch zwischen P [i] und T [k + i − 1], so existiert auch ein Mismatch zwischen P [i − 3] und T [j + i − 4] = T [k + i − 1].

x x ······ ······y k j k j

27 Algorithmus 1.12 Algorithmus von Vishkin: 2. Phase Eingabe: W¨orter P ,T , |P | = m, |T | = n, Stack C (aus der 1. Phase) Ausgabe: Menge S der Vorkommen von P in T (1) k ← Pop(C); i ← 1; j ← k; (2) while k ≤ n (3) while i ≤ m and P (i) = T (j) (4) i ← i + 1; j ← j + 1; (5) if i > m then (6) S ← S ∪ {k}; k ← Pop(C); (7) if k ≤ j then i ← j − k + 1; (8) else j ← k; i ← 1; (9) else (10) while k ≤ j (11) k ← Pop(C); (12) j ← k; i ← 1;

Satz 1.21 Algorithmus 1.12 bestimmt die Vorkommen von P in T mit einem Aufwand von O(n). Beweis. Die Korrektheit folgt aus den Eigenschaften von C und Lemma 1.17 (2). Die lineare Laufzeit ergibt sich, da mit jedem Match der Wert von j erh¨oht mit jedem Mismatch der Stack verringert wird. 2

Parallelisierung Die Bedeutung des Algorithmus von Vishkin liegt darin, daß er sich parallelisieren l¨aßt. In den folgenden Betrachtungen verwenden wir das Modell der CREW PRAM (concurrent read, exclusive write). Ist p die kleinste Periodenl¨ange von P , so teilt man den Text T in Intervalle der L¨ange p. In jedem Intervall kann es h¨ochstens ein Vorkommen von P geben. Man kann durch Duelle in log2 p parallelen Schritten und mit einer Gesamtarbeit von Θ(n) einen Kandidaten fur¨ jedes Intervall ermitteln. Gilt p > m/2, so wird unter Anwendung des parallelisierten Naiven Algorithmus fur¨ jeden Kandidaten getestet, ob tats¨achlich ein Vorkommen von P vorliegt. Dies ist fur¨ einen Kandidaten mit einem Zeitaufwand von Θ(log m) und einem Arbeitsaufwand von Θ(m), d.h. mit einem gesamten Arbeitsaufwand von Θ(n) m¨oglich. Gilt hingegen p ≤ m/2, so hat P die Form P = ukv mit u = P [1 . . . p], k ≥ 2, v = P [1 . . . i] mit i = m mod p. Wir ermitteln zun¨achst, wie im nicht-periodischen Fall, alle Vorkommen des Wortes u2v (dieses Wort hat die kleinste Periode p). Dies ist mit einem Zeitaufwand von Θ(log p) und einem gesamten Arbeitsaufwand von Θ(n) m¨oglich. Nun kommt an einer Position j das Wort P genau dann vor, wenn an jeder der Positionen j, j + p, j + 2p, . . . , j + (k − 2)p das Wort u2v vorkommt. Dies kann mit einem Zeitaufwand von Θ(log k) und einem gesamten Arbeitsaufwand von Θ(n) ermittelt werden. Weitere Informationen zur parallelen exakten Wortsuche findet man in Kapitel 2 des Buches von Apostolico und Galil sowie im Kapitel 7 des Buches An Introduction to Parallel Algorithms von Joseph J´aJ´a.

28 1.8 Der Shift-And-Algorithmus

Der Shift-And-Algorithmus ist ein relativ neuer Algorithmus, der die durch Bit-Arithmetik m¨ogliche Parallelisierung ausnutzt. Er ist praktikabel fur¨ die Suche nach P in T , wenn die L¨ange von P nicht gr¨oßer ist als die Zahl der Bits in einem Computerwort (zur Zeit also 32 bzw. 64). Zur Bearbeitung von Computerw¨ortern (Bytes) benutzen wir die Operationen & (bitweises AND), | (bitweises OR), ˜ (bitweises NOT), << (Verschiebung der Bits nach links), >> (Verschiebung der Bits nach rechts). Es besteht ein enger Zusammenhang zum nichtdeterministischen Automaten (NEA), der die Sprache Σ∗P akzeptiert. Dieser NEA hat fur¨ |P | = m die Form

AP = (Σ, {0, 1, . . . , m}, δ, 0, {m}) mit

δ = {(i, P [i + 1], i + 1) : 0 ≤ i < m} ∪ {(0, x, 0) : x ∈ Σ}.

Beispiel 1.11 Fur¨ P = abcabba ergibt sich der folgende NEA:

- a- b- c- a- b- b- a- 0 1 2 3 4 5 6 7 m6 m m m m m m m Σ  ¦ ¥ Im Shift-And-Algorithmus wird die Menge der erreichbaren Zust¨ande durch ein Byte Z kodiert. Dabei entspricht dem Zustand i ∈ {1, 2, . . . , m} das i-te Bit von rechts in Z. Da der Zustand 0 immer erreichbar ist, wird er nicht kodiert. Nach dem Einlesen des Textes T [1 . . . j] hat das i-te Bit von rechts den Wert 1 genau dann, wenn der Zustand i mit dem Wort T [1 . . . j] erreichbar ist. Ein Vorkommen von P endet an der Stelle j genau dann, wenn das m-te Bit von rechts den Wert 0 besitzt. Im Pr¨aprozessing wird jedem Buchstaben x ∈ Σ ein Byte B[x] zugewiesen. In B[x] ist das i-te Bit von hinten genau dann 1, wenn P [i] = x gilt. Bei der Initialisierung von Z erh¨alt das erste Bit von hinten den Wert 1. Die Aktualisierungsregel fur¨ Z an der Textstelle j lautet

Z ← ((Z<<1) | 1) & B[T [j]], benutzt also die Shiftoperation und die And-Operation, was dem Algorithmus den Namen gab.

Algorithmus 1.13 Shift-And-Algorithmus Eingabe: W¨orter P , T mit |P | = m, |T | = n Ausgabe: Menge S der Vorkommen von P in T (1) foreach x ∈ Σ (2) B[x] ← 0; (3) for i ← 1 to m (4) B[P [i]] ← B[P [i]] | (1<<(i − 1)); (5) S ← ∅; Z ← 1; (6) for j ← 1 to n (7) Z ← ((Z<<1) | 1) & B[T [j]]; (8) if Z & (1<<(m − 1)) 6= 0 then S ← S ∪ {j − m + 1};

29 Beispiel 1.12 Fur¨ Σ = {a, b, c}, P = abcabba und T = abaabcabbab ergibt sich folgender Ablauf des Algorithmus (das rechteste Bit von Z ist unten). Das Ende eines Vorkommens erkennt man am 7. Bit von rechts.

Ba Bb Bc a b a a b c a b b a b 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 1 1 0 0 0 1 0 1 1 0 0 1 0 0 1 0

Satz 1.22 Es seien P und T W¨orter uber¨ Σ mit |P | = m, |T | = n und |Σ| = σ, wobei m nicht gr¨oßer als eine Byte-L¨ange ist. Der Shift-And-Algorithmus findet alle Vorkommen von P in T in einer Zeit von O(n) und ben¨otigt fur¨ das Pr¨aprozessing eine Zeit von O(m + σ). Beweis. Zum Beweis der Korrektheit zeigt man per Induktion, daß das i-te Bit von hin- ten tats¨achlich genau dann 1 ist, wenn der Zustand 0 im NEA erreichbar ist. Die Laufzeit- absch¨atzung ist trivial. 2 Fur¨ hinreichend kurze Suchw¨orter P (was in diesem Falle normale L¨angen sind) liefert der Shift-And-Algorithmus also einen Realtime-Algorithmus zur exakten Wortsuche. Da die Operationen auf Bit-Ebene erfolgen, sind Implementierungen auch sehr schnell. Die Haupt- bedeutung ist des Shift-And-Algorithmus jedoch, daß er ohne weiteres auf das Problem der inexakten Suche verallgemeinert werden kann. Ursprunglich¨ wurde eine andere Variante (Baeza-Yates und Gonnet, 1989) eingefuhrt,¨ bei der die Bits die umgekehrte Bedeutung haben: eine 0 entspricht einem erreichbaren Zustand. Die Aktualisierung benutzt die Shift- sowie die Or-Operation; der Algorithmus wird deshalb Shift-Or-Algorithmus genannt. Der Shift-And-Algorithmus stammt von Wu und Manber (1992), die auch die Implemen- tierung der inexakten Suche mittels des Shift-And-Algorithmus im Programm agrep vornah- men.

1.9 Algorithmen mit Suffixautomaten

Der Boyer-Moore-Algorithmus vergleicht in einer Phase so lange, wie der Text mit einem Suffix σ des Suchwortes ubereinstimmt.¨ Wie bereits gesehen, ist die mittlere Zahl der Vergleiche σ−1 , und die mittlere Verschiebung betr¨agt σ. Um gr¨oßere Verschiebungen zu erreichen, kann man die erweiterte Bad Character-Regel benutzen. Eine andere Idee besteht nun darin, die Vergleiche in einer Phase so lange fortzusetzen, wie der Text mit einem Infix des Suchwortes ubereinstimmt.¨ Ist T [j + 1 . . . k] ein Infix von P , T [j . . . k] aber nicht, so kann ein Vorkommen von P fruhestens¨ an der Stelle j+1 beginnen, d.h. man kann das Suchfenster um k −j Stellen verschieben. Sollte an der Stelle k ein Vorkommen von P enden, so verschiebt man um eine Stelle.

30 - P P T j k Zur Bestimmung des l¨angsten Infixes von P an einer Textstelle verwendet man den Suf- fixautmaten von P r.

Definition 1.11 Es sei w ein Wort. Der Suffixautomat (auch DAWG fur¨ Directed Acyclic Word Graph) ist der minimale deterministische endliche Automat, dessen akzeptierte Sprache die Menge der Suffixe von w ist.

Beispiel 1.13 Fur¨ P = abcabba ergibt sich der folgende DAWG von P r = abbacba:

8 a 9  Qk c  b Q b + j) j Q 0 1 2  3 4 5 6 7   a b c a b b a  j j j6 j j jc jc j   

Algorithmus 1.14 Backward DAWG Matching (BDM-Algorithmus) Eingabe: W¨orter P , T uber¨ Σ mit |P | = m, |T | = n Ausgabe: Menge S der Vorkommen von P in T r (1) Konstruiere den DAWG fur¨ P A = (Σ, Z, δ, z0,F ); (2) S ← ∅; z ← z0; k ← m; (3) while k ≤ n (4) j ← k; (5) while δ(z, T [j]) existiert (6) z ← δ(z, T [j]); j ← j − 1; (7) if j = k − m then S ← S ∪ {k − m + 1}; k ← k + 1; (8) else k ← j + m;

Die Verschiebungsregel kann noch etwas verfeinert werden. Erreicht der DAWG von P r einen Endzustand, so bedeutet dies, daß ein Pr¨afix von P gefunden wurde. Man darf also bis an die Stelle des Textes verschieben, wo das letzte Mal ein Endzustand festgestellt wurde. Wurde ein Vorkommen von P gefunden, so verschiebt man um Per(P ) Stellen.

Beispiel 1.14 Fur¨ das Wort P = abcabba und die Textzeichen acab ergibt sich das l¨angste Infix cab. Das l¨angste Pr¨afix ist aber ab, d.h. es ist eine Verschiebung um 7 − 2 = 5 m¨oglich.

Satz 1.23 Algorithmus 1.14 findet alle Vorkommen von P in T . Beweis. Die Korrektheit des BDM-Algorithmus folgt aus den Vorbetrachtungen. 2 Die Laufzeit im schlechtesten Fall betr¨agt Θ(m · n). Im Durchschnittsfall ist die Laufzeit   Θ n·`m , wobei ` die mittlere L¨ange des l¨angsten Teilwortes von P ist, das Suffix eines m−`m m Wortes der L¨ange m ist. Man kann zeigen, daß `m ≈ logσ m gilt, d.h. die mittlere Laufzeit

31   n·logσ m ist in der Gr¨oßenordnung Θ m und damit optimal. Durch Kombination mit Ideen des KMP-Algorithmus kann man einen Algorithmus gewinnen, der im schlechtesten Fall in linearer Zeit l¨auft und im Durchschnittsfall nur um einen konstanten Faktor langsamer wird. Was das Pr¨aprozessing betrifft, so kann man zeigen, daß der DAWG eines Wortes der L¨ange m h¨ochstens 2m Knoten und 4m Kanten besitzt und in linearer Zeit konstruiert werden kann. Dennoch ist die Konstruktion relativ aufwendig und verlangsamt die praktische Laufzeit im Vergleich etwa zum Horspool-Algorithmus mit erweiterter Bad Suffix Regel. Es gibt aber zwei weitere Algorithmen, die einfachere Automaten benutzen. Der erste beruht auf Bitarithmetik und benutzt den Suffix-NEA (auch nichtdeterministischer DAWG, NDAWG) fur¨ P r.Fur¨ ein Wort P ∈ Σ∗ der L¨ange m ist der Suffix-NEA fur¨ P r der Automat

AP = (Σ, {0, 1, . . . , m}, δ, {0, 1, . . . , m}, {0}) mit δ = {(i, P [i], i − 1)} fur¨ 1 ≤ i ≤ m.

Beispiel 1.15 Fur¨ P = abcabba ergibt sich der folgende Suffix-NEA von P r = abbacba:

a b c a b b a 0 1 2 3 4 5 6 7 6m6 m m6 m6 6 m6 m m6 m6  Die Simulation des Suffix-NEA erfolgt ¨ahnlich wie beim Shift-Or-Algorithmus. Im Pr¨aprocessing wird jedem Buchstaben x ∈ Σ ein Byte B[x] zugewiesen. In B[x] ist das i-te Bit von hinten genau dann 1, wenn P [i] = x gilt. Die Menge der erreichbaren Zust¨ande sind in einem Byte Z kodiert, wobei das i-te Byte von rechts genau dann den Wert 1 besitzt, wenn der Zustand i − 1 erreichbar ist. Bei der Initialisierung von Z erhalten die ersten m + 1 Bits von hinten den Wert 1. Die Aktualisierungsregel fur¨ Z lautet Z ← (Z>>1) & B[T [j]].

Algorithmus 1.15 BNDM-Algorithmus Eingabe: W¨orter P , T mit |P | = m, |T | = n Ausgabe: Menge S der Vorkommen von P in T (1) foreach x ∈ Σ (2) B[x] ← 0; (3) for i ← 1 to m (4) B[P [i]] ← B[P [i]] | (1<<(i − 1)); (5) S ← ∅; k ← m; (6) while k ≤ n (7) Z ← (1<<(m + 1)) − 1; j ← k; (8) while Z 6= 0 (9) Z ← (Z>>1) & B[T [j]]; (10) if j = k − m then S ← S ∪ {k − m + 1}; k ← k + 1; (11) else k ← j + m;

Die Verschiebungsregel kann auch hier verfeinert werden. Erreicht der NDAWG von P r seinen Endzustand, so bedeutet dies, daß ein Pr¨afix von P gefunden wurde. Man kann also bis

32 an die Stelle verschieben, wo das letzte Mal ein Endzustand festgestellt wurde. Das Erreichen des Endzustandes ist diesmal sehr einfach zu festzustellen; man muß nur testen, ob das letzte Bit auf 1 steht. Der BNDM-Algorithmus ist sehr schnell fur¨ kurze Suchw¨orter (bis zu zwei Byte-L¨angen). Fur¨ gr¨oßere Suchw¨orter sind die sogenannten Orakel-Automaten eine praktikable Version der Suffix-Automaten. Der Orakel-Automat fur¨ ein Wort P akzeptiert alle Infixe von P und noch weitere W¨orter. Benutzt man bei der Suche nach P den Orakel-Automaten fur¨ P r, so gelten die gleichen Verschiebungsregeln wie fur¨ die Suche mit dem DAWG. Da zus¨atzliche W¨orter akzeptiert werden, werden in einer Suchphase mehr Schritte gemacht, und die Ver- schiebung ist kurzer¨ als beim DAWG. Dafur¨ ist der Orakel-Automat einfacher zu konstruieren als der DAWG.

1.10 Karp-Rabin-Algorithmus

Die Idee des Karp-Rabin-Algorithmus ist, ein Wort u ∈ Σm auf seinen “Fingerabdruck” (Hash-Funktion) Hash(u) ∈ IN abzubilden. Im Laufe des Algorithmus werden die Werte Hash(Tk) = Hash(T [k . . . k − m + 1]) fur¨ 1 ≤ k ≤ n − m + 1 gebildet. Stimmt Hash(Tk) nicht mit Hash(P ) uberein,¨ so kommt an der Stelle k garantiert nicht das Wort P vor. Anderenfalls kann P an der Stelle k vorkommen, es muß aber nicht. Der Karp-Rabin-Algorithmus liefert also eine Menge von Kandidaten fur¨ das Vorkommen von P in T . Damit der Algorithmus effizient abl¨auft, sollten folgende Bedingungen erfullt¨ sein:

• Die Funktion Hash berechnet fur¨ ¨ahnliche W¨orter unterschiedliche Werte.

• Hash(Tk+1) ist aus Hash(Tk) in konstanter Zeit berechenbar. Wir nehmen o.B.d.A. an, daß Σ = {0, 1, . . . , σ − 1} ist. Dann k¨onnen wir ein Wort w = x1x2 . . . xm−1xm mit der Zahl m X m−i H(w) = xi · σ i=1 identifizieren. Als Hash-Funktion eignet sich Hashq(w) = H(w) mod q, wobei q eine Primzahl ist. Fur¨ a, b ∈ Σ und α ∈ Σm−1 gilt H(αb) = H(aα) · σ − a · σm + b und folglich

m Hashq(αb) = (Hashq(aα) · σ − a · (σ mod q) + b) mod q.

Damit berechnet sich Hashq(Tk+1) als

Hashq(Tk+1) = (Hash(Tk) · σ − T [k] · s + T [k + m]) mod q, wobei s = σm mod q ist. Wegen σk mod q = (σ · (σk−1 mod q)) mod q fur¨ alle k ∈ IN kann man s mit einem Aufwand von Θ(m) berechnen. Damit kann man also Hashq(Tk+1) mit konstanten Aufwand aus Hashq(Tk) berechnen. Analog k¨onnen Hashq(P ) und Hashq(T1) mit einem Aufwand von Θ(m) berechnet werden.

33 Algorithmus 1.16 Karp-Rabin-Algorithmus Eingabe: W¨orter P , T uber¨ Σ = {0, 1, . . . , σ − 1} mit |P | = m, |T | = n Ausgabe: Menge C m¨oglicher Vorkommen von P in T (1) C ← ∅; (2) W¨ahle eine Primzahl q; m (3) s ← σ mod q; h ← Hashq(P ); H ← Hashq(T [1 . . . m]); (4) if H = h then C ← C ∪ {1}; (5) for k ← 1 to n − m (6) H ← (H · σ − T [k] · s + T [k + m]) mod q; (7) if H = h then C ← C ∪ {k + 1};

Beispiel 1.16 Es seien Σ = {0, 1, 2, 3}, P = 30303, T = 10130303123231011203. Fur¨ q = 11 bzw. q = 17 erhalten wir folgenden Ablauf. (Die Werte Tk sind an die Stelle k + m − 1 = k + 4 geschrieben.) m q Hashq(P ) σ mod q 11 5 1 17 3 4 q 1 0 1 3 0 3 0 3 1 2 3 2 3 1 0 1 1 2 0 3 11 9 5 9 5 7 8 10 9 3 1 2 6 1 3 0 3 17 12 13 1 3 1 6 15 11 1 1 13 7 4 6 3 15 Es bleibt nach diesen beiden L¨aufen nur die Stelle 4 als m¨ogliches Vorkommen. 2 Es gibt jetzt unterschiedliche M¨oglichkeiten, mit der Kandidatenmenge C umzugehen. 1. Man kann fur¨ jeden der Kandidaten zu testen, ob ein Vorkommen von P vorliegt. Im schlechtesten Fall ben¨otigt man einen Aufwand von O(mn). 2. Man kann die Menge C als Ergebnis ausgeben. Damit haben wir einen probabilistischen Algorithmus, der ein fehlerhaftes Ergebnis liefern kann (n¨amlich Vorkommen zu deklarieren, wo keine sind). Im Abschnitt 4.4 des Buchs von Gusfield wird die Fehlerwahrscheinlichkeit genauer untersucht. W¨ahlt man q als zuf¨allige Primzahl aus dem Intervall [1, mn2], so betr¨agt die Fehlerwahrscheinlichkeit (fur¨ jede Eingabe) O(1/n). Wiederholt man den Algorithmus k-mal und gibt die Menge aller Kandidaten aus, die jedes Mal gefunden wurden, so reduziert sich die Fehlerwahrscheinlichkeit auf O(1/nk). 3. Man kann mit einem Aufwand von O(n) testen, ob die Kandidatenliste C einen Fehler enth¨alt. Wird ein Fehler gefunden, so wiederholt man den Algorithmus (mit einer neuen Primzahl). Fur¨ den Test teilt man die geordnete Kandidatenliste C in geordnete Teillisten C1,C2,...,Cr auf, wobei ein Element zu seinem Nachfolger in einer Liste Ci h¨ochstens den Abstand m/2 hat, w¨ahrend der Abstand vom letzten Element von Ci zum ersten Element von Ci+1 gr¨oßer als m/2 ist. Betrachten wir nun eine Teilliste Ci = {k1, k2, . . . , kt}. Wir prufen¨ zun¨achst, ob an den Stellen k1 und k2 ein Vorkommen von P vorliegt. Sollte dies nicht der Fall sein, so enth¨alt C einen Fehler. Anderenfalls ist d = k2 −k1 die kleinste Periode von P (Beweis UA).¨ Wenn alle Kandidaten aus Ci korrekt sind, so muß der Abstand zweier benachbarter Kandidaten jeweils d sein. Wir prufen¨ deshalb als n¨achstes, ob kj − kj−1 = d fur¨ 3 ≤ j ≤ t gilt. Sollte dies nicht der Fall sein, so enth¨alt C einen Fehler. Anderenfalls brauchen wir fur¨ die m¨oglichen Vorkommen k3, . . . , kt nur die letzten d Positionen zu testen.

34 Variante 1 liefert einen deterministischen Algorithmus mit mittlerer Laufzeit O(n); Vari- ante 2 ist ein probabilistischer Algorithmus mit der Laufzeit O(n) und einer geringen Feh- lerwahrscheinlichkeit (Monte-Carlo-Algorithmus); Variante 3 ist ein probabilistischer Algo- rithmus mit korrektem Ergebnis und einer erwarteten Laufzeit von O(n) fur¨ jede Eingabe (Las-Vegas-Algorithmus). Interessant am Karp-Rabin-Algorithmus ist, daß bei der Suche keine kombinatorischen Eigenschaften des Suchwortes P benutzt werden. Dies macht den Algorithmus geeignet fur¨ die Suche nach komplizierteren Strukturen, z.B. zweidimensionalen Bildern.

1.11 Eine untere Schranke fur¨ Algorithmen zur Wortsuche

n log m Zum Abschluß dieses Kapitels soll bewiesen werden, daß sie mittlere Laufzeit von O( m ), wie sie z.B. der Boyer-Moore-Algorithmus erreicht, optimal ist. Wir folgen dabei im wesentli- chen den Ideen von Yao aus dem Jahr 1979 [15], beschr¨anken unsere Betrachtungen aber auf den Fall, daß n ≥ 2m gilt. Wir zeigen zun¨achst, daß man sich auf ein einfacheres Problem beschr¨anken kann, n¨amlich auf die Suche nach einem Wort der L¨ange m in einem Text der L¨ange 2m.

Lemma 1.24 Die mittlere Komplexit¨at des Problems der Suche nach einem Wort der L¨ange n m in einem Text der L¨ange n ≥ 2m betr¨agt Ω( m E(m)), wobei E(m) die mittlere Komplexit¨at des Problems der Suche nach einem Wort der L¨ange m in einem Text der L¨ange 2m ist. Beweis. Wir zerlegen einen Text der L¨ange n in disjunkte Bl¨ocke der L¨ange 2m und suchen nur nach Vorkommen, die komplett in einem dieser Bl¨ocke liegen. Jeder Algorithmus zur Suche nach allen Vorkommen kann in einen asymptotisch gleich schnellen Algorithmus zur Suche nach den Vorkommen in den Bl¨ocken umgewandelt werden (man muß nur die Vorkommen an Positionen der Form 2km + i mit 1 ≤ i ≤ m + 1 ausgeben). Andererseits ben¨otigt man zur Ermittlung aller Vorkommen in einem Block im Mittel E(m) Vergleiche in diesem (und nur n diesem) Block, insgesamt also fur¨ die Ermittlung der Vorkommen in allen Bl¨ocken 2m E(m) Vergleiche. 2 Es bleibt jetzt noch zu zeigen, daß der mittlere Aufwand E(m) fur¨ die Suche nach einem Wort der L¨ange m in einem Text der L¨ange 2m in der Gr¨oßenordnung Ω(log m) liegt.

2m Definition 1.12 Es sei • ∈/ Σ ein Symbol. Sm(l) ist die Menge aller W¨orter in (Σ ∪ {•}) 2m mit genau l Symbolen aus Σ.Fur¨ z ∈ Sm(l) ist I(z) die Menge aller W¨orter w ∈ Σ mit w[i] = z[i] fur¨ alle 1 ≤ i ≤ 2m mit z[i] ∈ Σ.

m Definition 1.13 Ein Wort z ∈ Sm(l) heißt Zertifikat fur¨ α ∈ Σ , falls α fur¨ alle W¨orter aus I(z) an den gleichen Stellen vorkommt.

Lemma 1.25 Es sei α ∈ Σm. Gibt es ein Wort T ∈ Σ2m, fur¨ das man alle Vorkommen von α mit h¨ochstens l Vergleichen finden kann, so gibt es fur¨ α ein Zertifikat aus Sm(l).

Es genugt¨ damit, folgenden Sachverhalt zu beweisen. Es existieren Konstanten c1 > 0, c2 > m 0, m0 ∈ IN derart, daß es fur¨ alle m ≥ m0 mindestens c1σ W¨orter gibt, die kein Zertifikat aus Sm(lm) mit lm = c2 logσ m besitzen (und folglich fur¨ jeden Text der L¨ange 2m mehr als lm Vergleiche ben¨otigen). Die mittlere Zeit fur¨ die Suche in einem Block der L¨ange 2m kann man dann nach unten durch E(m) ≥ c1c2 logσ m absch¨atzen.

35 Lemma 1.26 (Counting Lemma) Ein Wort z ∈ Sm(l) mit l < m ist fur¨ h¨ochstens

2 (1 − 1/σl)m/l · σm W¨orter aus Σm ein Zertifikat. Beweis. Es sei J die Menge der Positionen, an denen z ein Zeichen aus Σ hat. Wegen l < m kann z nur ein Zertifikat fur¨ W¨orter sein, die in keinem Wort aus I(z) vorkommen. Fur¨ 0 ≤ k ≤ m definieren wir Bk = {i : 1 ≤ i ≤ m ∧ k + i ∈ J}. Bk ist die Menge der Positionen, die relevant fur¨ das Nicht-Vorkommen eines Wortes aus Σm an der Stelle k + 1 in den W¨ortern aus I(z) sind. Es sei α ∈ Σm ein Wort, fur¨ das z ein Zertifikat ist. Da α in keinem Wort aus I(z) vorkommt, gibt es fur¨ alle 0 ≤ k ≤ m ein i ∈ Bk mit α[i] 6= z[k + i]. Wir konstruieren jetzt eine Menge K = {k1, k2, . . . , kt} ⊆ {0, 1, . . . , m}, so daß die Mengen 0 Bk mit k ∈ K paarweise disjunkt sind. Wir setzen k1 = 0 und definieren ks induktiv als das 0 gr¨oßte k, fur¨ das Bk und B = Bk1 ∪ Bk2 ∪ ... ∪ Bks−1 nicht disjunkt sind. Ist ks kleiner 0 0 als m, so ist ks = ks + 1; anderenfalls ist t = s − 1. Fur¨ alle k ∈ {0, 1, . . . , ks} gibt es ein 0 jk ∈ B ∩Bk. Die ks +1 Paare (jk, k +jk) sind paarweise verschieden. Fur¨ die Wahl von jk gibt es h¨ochstens |B| ≤ l(s − 1) M¨oglichkeiten; fur¨ die Wahl von k + jk gibt es h¨ochstens |J| = l 2 0 2 M¨oglichkeiten. Insgesamt gibt es h¨ochstens l (s − 1) verschiedene Paare, d.h. ks < l (s − 1), d.h. |K| = t ≥ dm/l2e. m Soll z nun ein Zertifikat fur¨ α ∈ Σ sein, muß insbesondere fur¨ jedes k ∈ K ein i ∈ Bk derart existieren, daß α[i] 6= z[k + i] gilt. Fur¨ jedes k ∈ K gibt es σ|Bk| − 1 M¨oglichkeiten, die Zeichen {α[i]: i ∈ Bk} zu w¨ahlen. An den Stellen i, die in keiner Menge Bk (k ∈ K) liegen, gibt es jeweils σ M¨oglichkeiten fur¨ die Wahl von α[i]. Insgesamt kann man die Zahl der W¨orter, fur¨ die z ein Zertifikat darstellt, absch¨atzen durch Y 2 (1 − 1/σ|Bk|)σm ≤ (1 − σl)|K|σm ≤ (1 − 1/σl)dm/l eσm. k∈K 2

44 1 m Lemma 1.27 Es sei m > 2 und l = 2 logσ m. Die Anzahl Zm(l) der W¨orter aus Σ , die −1 m ein Zertifikat aus Sm(l) besitzen, ist kleiner als e σ .

Beweis. Zm(l) kann wie folgt abgesch¨atzt werden.   2 2m 2 Z (l) ≤ |S (l)|(1 − 1/σl)m/l σm = σl(1 − 1/σl)m/l σm m m l 2 ≤ (2mσ)l(1 − 1/σl)m/l σm  m  ≤ (2mσ)l exp − · σm (wegen ln(1 − 1/σl) ≤ −1/σl) l2σl  m  = exp ln(2mσ) · l − · σm. l2σl 1 Nach Einsetzen von l = 2 logσ m ergibt sich die Absch¨atzung !  1 4m  1 4m1/2 Z (l) ≤ exp ln(2mσ) · log m − σm = exp ln(2mσ) · log m − σm. m σ 2 1/2 σ 2 2 (logσ m) m 2 (logσ m)

44 4m1/2 1 −1 m Fur¨ m > 2 gilt 2 > ln(2mσ) · logσ m + 1 und damit Zm(l) < e σ . 2 (logσ m) 2

36 Satz 1.28 Fur¨ die Suche nach einem Wort der L¨ange m > 244 in einem Text der L¨ange 1−1/e n logσ m n ≥ 2m ben¨otigt man im Mittel mindestens 2 m Vergleiche. Zu bemerken ist, daß die Absch¨atzungen sehr großzugig¨ ausgefallen sind. Die Aussage von Satz 1.28 durfte¨ fur¨ sehr viel kleinere Werte von m gelten.

37 Kapitel 2

Exakte Suche nach komplexen Mustern

H¨aufig sucht man nicht nach einem bestimmten Wort, sondern nach W¨ortern, die zu einem be- stimmten Muster passen. Viele UNIX-Werkzeuge (grep, sed, awk), Editoren (vi, emacs) sowie Programmiersprachen (Perl) erlauben z.B. die Suche nach und die Manipulierung von regul¨aren Ausdrucken¨ .Fur¨ die Suche nach regul¨aren Ausdrucken¨ der L¨ange m ergibt die Kon- struktion nach Thompson einen ¨aquivalenten NEA mit Θ(m) Zust¨anden und Transitionen. Diese Konstruktion wird in der Grundvorlesung Theoretische Informatik behandelt, und wir werden auf einige Aspekte am Ende des Kapitels eingehen. Fur¨ einige speziellere Ausdrucke¨ kann man jedoch spezielle Algorithmen angeben, die effi- zienter als die Automatenkonstruktion sind. Als erstes betrachten wir die Suche nach endlich vielen W¨ortern. Fur¨ dieses Problem kann man einige Suchalgorithmen fur¨ einzelne W¨orter verallgemeinern. Danach betrachten wir die Suche nach zweidimensionalen Bildern. Am Ende kommen wir, wie bereits erw¨ahnt, zur Suche nach allgemeinen regul¨aren Ausdrucken.¨

2.1 Suche nach endlich vielen W¨ortern

Gegeben sind nun ein Text T und eine endliche Menge von W¨ortern P = {P1,...,Pr}. Gesucht sind alle Vorkommen von W¨ortern aus P in T , wobei ein Vorkommen von Pi an der Stelle k mit (k, i) angegeben wird. Die Anzahl der Suchw¨orter kann h¨aufig gr¨oßer sein als die L¨ange des Textes, z.B. bei der Suche nach Mustern in einer DNA-Sequenz. Fur¨ die weiteren Betrachtungen seien

r X |T | = n, |P| = r, |Pi| = M, max{|Pi| : 1 ≤ i ≤ r} = m, min{|Pi| : 1 ≤ i ≤ r} = µ. i=1 Die Idee fur¨ die simultane Suche nach den W¨ortern aus P ist, einen gerichteten Baum zu konstruieren, dessen Pfade mit den Suchw¨ortern beschriftet sind. Formal definieren wir den Suchwort-Baum (auch von retrieval tree) wie folgt:

Definition 2.1 Es sei P = {P1,...,Pr} eine Menge von W¨ortern. Der Suchwort-Baum (Trie) fur¨ P ist der gerichtete Baum Trie(P), der folgende Bedingungen erfullt:¨ 1. Jede Kante ist mit genau einem Buchstaben beschriftet.

38 2. Keine zwei Kanten mit dem gleichen Ausgangsknoten haben die gleiche Beschriftung.

3. Jeder Knoten v hat eine Information info(v) ∈ {0, 1, . . . , r}. Ist die Beschriftung L(v) des Weges von der Wurzel nach v ein Wort Pi mit 1 ≤ i ≤ r, so gilt info(v) = i; anderenfalls ist info(v) = 0.

4. Ist v ein Blatt, so gilt L(v) ∈ P.

5. Fur¨ jedes Wort P ∈ P gibt es einen Knoten v mit L(v) = P .

Beispiel 2.1 Der Suchwort-Baum fur¨ P = {aabab, ab, abb, baba} sieht wie folgt aus (die Wur- zel ist durch den Pfeil von außen gekennzeichnet): a b a b 1 a j@ j j j j b@ - @ 2b 3 j@ j j @ b @ 4 a b a j j j j Naiver Algorithmus Fur¨ jede Textstelle k suchen wir von der Wurzel des Suchwort-Baumes nach dem l¨angsten Pfad, dessen Beschriftung ein Pr¨afix von T [k . . . n] ist. Fur¨ jeden erreichten Knoten v, dessen Beschriftung ein Wort aus P ist, wird das Vorkommen von L(v) an Stelle k mitgeteilt. Ist der Weg nicht mehr fortsetzbar, erh¨ohe k um 1.

Algorithmus 2.1 Naive Suche mit Eingabe: Menge von W¨ortern P, Text T mit |T | = n Ausgabe: Menge S der Vorkommen von W¨ortern aus P in T (1) Konstruiere Trie(P) mit der Wurzel root. (2) S ← ∅; k ← 1; for k ← 1 to n (3) j ← k; v ← root; (4) while (es gibt in Trie(P) eine Kante (v, T [j], u)) (5) v ← u; j ← j + 1; (6) if info(v) > 0 then S ← S ∪ {(k, info(v))};

Die Laufzeit im schlechtesten Fall betr¨agt Θ(m) mit m = max{|P | : P ∈ P} fur¨ die Suche an einer Textstelle und insgesamt Θ(n · m). Auch im Durchschnitt ist die Laufzeit nicht mehr linear. Wir nehmen fur¨ unsere Betrachtungen der Einfachheit halber an, daß alle W¨orter aus P die gleiche L¨ange m besitzen und daß r  σm gilt, wobei σ die M¨achtigkeit des Alphabetes ist. Die Wahrscheinlichkeit eines Mismatches innerhalb der ersten i Vergleiche in einem Suchwort 1 ist 1 − σi .Fur¨ r unabh¨angig gew¨ahlte Suchw¨orter ist somit die Wahrscheinlichkeit eines 1 r Mismatches innerhalb der ersten i Zeichen in jedem Wort (1 − σi ) .W¨ahlt man i = logσ r, so 1 r erh¨alt man eine Wahrscheinlichkeit von 1−(1− r ) ≥ 1−1/e dafur,¨ daß mindestens ein Wort ¨ eine Ubereinstimmung der L¨ange logσ r mit dem Text aufweist. Damit betr¨agt die mittlere Zahl der Vergleiche je Versuch Ω(logσ r) und die Gesamtlaufzeit Ω(n · logσ r). Man kann auch

39 zeigen, daß die mittlere Zahl der Vergleiche je Versuch in der Gr¨oßenordnung von Θ(logσ r) liegt und damit die Gesamtlaufzeit Ω(n · logσ r) betr¨agt.

Aho-Corasick-Algorithmus Dieser Algorithmus ist die Verallgemeinerung des KMP-Algorithmus auf endliche Mengen von W¨ortern. Zun¨achst verallgemeinern wir den Begriff des Border-Wertes in geeigneter Weise auf Suchwort-B¨aume.

Definition 2.2 Fur¨ einen von der Wurzel verschiedenen Knoten v aus Trie(P) sei Border v der Knoten, fur¨ den L(Border v) das l¨angste echte Suffix von L(v) ist, das Pr¨afix eines Wortes aus P ist. Man bezeichnet Border v als Fehler-Link (failure link) von v.

Beispiel 2.2 Fur¨ P = {aabab, ab, abb, baba} erhalten wir folgende Fehler-Links:

© a b a b 1 @ a jO j j j j ? b@ - @ © 2b 3 j6@ jI j b@ @ © + + 4 a kb a j j j j Kommt man nun bei der Suche an eine Textstelle j und einen Knoten v, so daß sich von v keine Fortsetzung mit T [j] finden l¨aßt, so versucht man es von Border v aus weiter. Sollte v aber die Wurzel sein, so startet man eine neue Suche von j + 1 und der Wurzel. Wird an der Stelle j eine Fortsetzung zum Knoten u gefunden, so ist L(u) das l¨angste Suffix von T [1 . . . j], das Pr¨afix eines Wortes aus P ist. Ein Problem tritt allerdings auf, wenn W¨orter aus P Infixe von anderen W¨ortern aus P sind. So werden in unserem Beispiel P = {aabab, ab, abb, baba} fur¨ den Text aaababa an den Stellen 4 bzw. 6 die Knoten mit der Beschriftung aab bzw. bab erreicht, jedoch nicht der Knoten mit der Beschriftung ab. Gel¨ost wird das Problem durch Ausgabe-Links.

Definition 2.3 Fur¨ einen von der Wurzel verschiedenen Knoten v aus Trie(P) sei outv der Knoten, fur¨ den L(outv) das l¨angste echte Suffix von v ist, das ein Wort aus P ∪{ε} ist. Man bezeichnet outv als Ausgabe-Link (output link) von v.

Beispiel 2.3 Fur¨ P = {aabab, ab, abb, baba} erhalten wir folgende Ausgabe-Links (Links zur Wurzel sind weggelassen):

a b a b 1 a j@ j j j j b@ - @ ©) 2b 3 j@ jI j @ b @ 4 a b a j j j j

40 Im Pr¨aprozessing fur¨ den Aho-Corasick-Algorithmus (AC-Pr¨aprozessing) ist der Suchwort- Baum einschließlich Fehler- und Ausgabe-Links zu konstruieren. Der Baum selbst kann leicht in Linearzeit konstruiert werden: Man konstruiert zuerst einen mit P1 beschrifteten Weg und fugt¨ anschließend den Weg fur¨ jedes weitere Wort ein. Die Ermittlung der Fehler- und Ausgabe-Links geschieht ¨ahnlich wie die Bestimmung der Border i-Werte beim KMP-Algorithmus.

Algorithmus 2.2 AC-Pr¨aprozessing Eingabe: Menge von W¨ortern P Ausgabe: Trie(P) mit Fehler- und Ausgabe-Links (1) Konstruiere Trie(P) mit Wurzel root; (2) foreach Knoten v der Tiefe 0 oder 1 (3) Border v ← root; outv ← root; (4) foreach Knoten v der Tiefe > 1 in BFS-Ordnung (5) x ← Beschriftung der Kante (parent(v), v); (6) t ← Border parent(v); (7) while (es gibt keine Kante (t, x, u) and t 6= root) (8) t ← Border t; (9) if es gibt Kante (t, x, u) then Border v ← u; (10) else Border v ← root; (11) if L(Border v) ∈ P ∪ {ε} then outv ← Border v;

(12) else outv ← outBorder v ;

Satz 2.1 Algorithmus 2.2 erzeugt den Suchwort-Baum fur¨ P (einschließlich Fehler- und Ausgabe-Links) mit einem Aufwand von O(M).

Beweis. Die Korrektheit wie auch die Laufzeitabsch¨atzung werden ¨ahnlich wie fur¨ das KMP- Pr¨aprozessing (siehe Satz 1.7) bewiesen. 2

Algorithmus 2.3 Aho-Corasick-Algorithmus Eingabe: Menge von W¨ortern P, Text T Ausgabe: Menge S der Vorkommen von W¨ortern aus P in T (1) S ← ∅; j ← 1; v ← root; (2) while j ≤ |T | (3) while es gibt keine Kante (v, T [j], u) and v 6= root (4) v ← Border v; (5) if es gibt Kante (v, T [j], u) then v ← u; (6) if info(v) > 0 then (7) S ← S ∪ {(j − Tiefe(v) + 1, info(v))}; (8) t ← outv; (9) while t 6= root (10) S ← S ∪ {(j − Tiefe(t) + 1, info(t))}; (11) t ← outt; (12) j ← j + 1;

41 Satz 2.2 Algorithmus 2.3 findet die Vorkommen aller W¨orter aus P in T mit einem Aufwand von O(n + A), wobei A die Anzahl der Vorkommen ist. Beweis. Analog zum KMP-Algorithmus (Satz 1.6). 2

Der Commentz-Walter-Algorithmus Der Commentz-Walter-Algorithmus ist die Verallgemeinerung des Boyer-Moore-Algorithmus auf endlich viele W¨orter. Sind die W¨orter P = {P1,P2,...,Pr} gesucht, so konstruiert man r r r r den Suchwort-Baum fur¨ P = {P1 ,P2 ,...,Pr }. In einer Phase vergleicht man den Text von rechts nach links mit den Zeichen des Baumes von der Wurzel aus und verschiebt entsprechend der (erweiterten) Bad-Character-Regel oder der Good-Suffix-Regel.

∗ ∗ 0 Definition 2.4 Fur¨ α ∈ Σ , P ∈ Σ , |P | = m ≥ q sei Rα(P ) die rechteste Stelle in P = P [1 . . . m − 1], an der ein Vorkommen von α endet oder die L¨ange des l¨angsten Suffixes von 0 α, das Pr¨afix von P ist, falls α nicht in P auftritt. Außerdem sei Shα(P ) = m − Rα(P ). ∗ Fur¨ eine endliche Menge P von W¨ortern aus Σ setzen wir Shα(P) := min{Shα(P ): P ∈ P}

Tritt am rechten Ende des aktuellen Suchbereiches das Wort α auf, so ist Shα(P) eine Verschiebung, die garantiert kein Vorkommen eines Wortes aus P ubergeht.¨ Offensichtlich ist die Verschiebung durch die L¨ange µ des kurzesten¨ Wortes aus P beschr¨ankt. Angewendet wird die Verschiebung wiederum als Bad-Character- bzw. Good-Suffix-Regel. Erweiterte Bad-Character-Regel. Man w¨ahlt eine Zahl q ≥ 1 und bestimmt im q Pr¨aprozessing die Werte Shα(P) fur¨ alle α ∈ Σ . Ergeben bei der Suche die letzten q Zeichen des aktuellen Textes das Wort α, so darf man um Shα(P) Stellen verschieben.

Good-Suffix-Regel. Im Pr¨aprozessing bestimmt man die Werte Shβ(P) fur¨ alle β, die Suffix eines Wortes P ∈ P sind. Gespeichert werden sie Werte als Feld Sh uber¨ den Knoten von Trie(Pr). Dabei gilt Sh[v] = Shβ mit β = L(v). Gelangt man bei der Suche bis zu einem Knoten v des Baumes Trie(Pr), so darf man um Sh[v] Stellen verschieben.

Beispiel 2.4 Fur¨ P = {aababba, abbbaaab, abbaaaba} ergibt sich folgender Suchwort-Baum fur¨ Pr mit den Werten Sh[v] fur¨ die Good-Suffix-Verschiebung. 3 3 3 3 3 3 3 1 a b b a a a b 3 @ j j j j j j j j a 4 4 4 4 3 b @ 1 a a b a @ 1 

j j j j j j 4 4 1 1 1 1 1 1 b a b b b a a a 2 j j j j j j j j Als Bad-Character-Verschiebung mit q = 3 ergeben sich folgende Werte:

α aaa aab aba abb baa bab bba bbb Shα 1 1 3 1 2 2 3 4 Die mittlere Verschiebung nach der Bad-Character-Regel betr¨agt hier 17/8.

42 Algorithmus 2.4 Commentz-Walter-Algorithmus Eingabe: Menge von W¨ortern P, Text T mit |T | = n Ausgabe: Menge S der Vorkommen von W¨ortern aus P in T (1) Konstruiere Trie(Pr) mit der Wurzel root; Bestimme Sh[v] fur¨ jeden Knoten v; q (2) W¨ahle q ≥ 1; Bestimme Shα(P) fur¨ alle α ∈ Σ ; (3) S ← ∅; k ← µ; (4) while k ≤ n (5) j ← k; v ← root; (6) while (es gibt in Trie(P) eine Kante (v, T [j], u)) (7) v ← u; j ← j − 1; (8) if info(v) > 0 then S ← S ∪ {(k − depth(v) + 1, info(v))}; (9) α ← T [k − q + 1 . . . k]; (10) k ← k + max{Shα, Sh[v]};

Satz 2.3 Der Commentz-Walter-Algorithmus findet alle Vorkommen von W¨ortern aus P in T . Wir wollen die mittlere Laufzeit des Commentz-Walter-Algorithmus bestimmen. Dabei betrachten wir wiederum die Variante, daß nur die verallgemeinerte Bad-Character-Regel benutzt wird. Wir nehmen an, daß r  σµ gilt. Die mittlere Zahl der Vergleiche pro Such- phase betr¨agt Θ(logσ r + q). Die Wahrscheinlichkeit, daß die Bad-Character-Verschiebung fur¨ 1 i ein Suchwort mindestens i + 1 betr¨agt, ist 1 − σq . Die Wahrscheinlichkeit, daß die Bad- 1 ir Character-Verschiebung fur¨ r unabh¨angige Suchw¨orter mindestens i+1 betr¨agt, ist 1 − σq . Die mittlere Verschiebung erhalten wir damit fur¨ hinreichend großes µ als

µ−1 ri X  1  1 1 1 − ≈ ≈ . σq 1 − 1 − 1 r 1 − e−r/σq i=0 σq

Als optimale Wahl fur¨ q erweist sich q = logσ(rµ), denn dann ergibt sich: 1 1 1 ≈ ≈ = µ. 1 − e−r/σq 1 − e−1/µ 1 − (1 − 1/µ)

logσ(µr) Insgesamt ergibt sich dann eine mittlere Laufzeit von O(n · µ ). Eine Verbesse- rung gegenuber¨ dem Aho-Corasick-Algorithmus wird damit nur erreicht, wenn die Anzahl r der Suchw¨orter nicht zu groß und die L¨ange µ des kurzesten¨ Suchwortes nicht zu klein sind. Fur¨ das Pr¨aprozessing erhalten wir eine Laufzeit von Θ(M) fur¨ die Bestimmung von Trie(Pr) und von Θ(σq) fur¨ die Bestimmung der Bad-Character-Verschiebung. Die Good- Suffix-Verschiebungen k¨onnen mit einem Aufwand von Θ(M) bestimmt werden; dies ist z.B. mit Hilfe von Suffixb¨aumen m¨oglich.

Einfluß der Alphabetgr¨oße Bisher haben wir die Gr¨oße des Alphabetes als eine Konstante angesehen. Die Alphabetgr¨oße wirkt sich dann auf die Laufzeit aus, wenn in einem Knoten nach einer ausgehenden Kante gesucht wird, die mit einem vorgegebenen Symbol x ∈ Σ markiert ist (z.B. Zeile 7 im AC- Pr¨aprozessing, Zeile 3 im AC-Algorithmus). Es bieten sich folgende M¨oglichkeiten an, die von einem Knoten ausgehenden Kanten zu speichern:

43 1. als Adjazenzliste,

2. als geordnetes Array,

3. als Array uber¨ der Indexmenge Σ.

Sei d(v) der Ausgangsgrad des Knoten v. Der Aufwand fur¨ die Suche nach einer Nachfol- gerkante von v betr¨agt O(d(v)) bei Variante 1, O(log(d(v))) bei Variante 2, O(1) bei Variante 3. Allerdings wird der Zeitgewinn bei Variante 3 durch einen h¨oheren Bedarf an Speicher- platz erkauft, und das bessere asymptotische Verhalten von Variante 2 macht sich erst bei mittelgroßen Werten von d(v) bemerkbar. Es bietet sich somit an, im Falle großer Alphabete fur¨ jeden Knoten je nach seinem Ausgangsgrad eine der Varianten zu w¨ahlen. Fur¨ einen klei- nen Grad ist Variante 1 am besten, fur¨ einen mittelgroßen Variante 2 und fur¨ einen großen Variante 3. Meistens werden hohe Ausgangsgrade nahe der Wurzel auftreten. Eine weitere M¨oglichkeit ist die Verwendung von Hash-Tabellen, bei der man ebenfalls mit linearem Platz und im Mittel mit linearem Zeitaufwand auskommt.

2.2 Suche nach zweidimensionalen Bildern

Ein zweidimensionales Bild der Gr¨oße (m1, m2) uber¨ dem Alphabet Σ ist eine (m1, m2)- Matrix P mit Eintr¨agen aus Σ. Wir nennen m1 auch die Breite und m2 die H¨ohe von P . Wir sagen, daß ein Bild P der Gr¨oße (m1, m2) im Bild T der Gr¨oße (n1, n2) an der Stelle (k1, k2) vorkommt, wenn T [k1 +i1 −1, k2 +i2 −1] = P [i1, i2] fur¨ alle 1 ≤ i1 ≤ m1 und alle 1 ≤ i2 ≤ m2 gilt. Im folgenden seien M = m1m2 und N = n1n2, d.h. die Anzahl der Bildpunkte von P bzw. T . Die Suche im zweidimensionalen Fall ist komplizierter als im eindimensionalen. Es lassen sich aber einige Ideen der eindimensionalen Suche verwenden. Im folgenden werden wir drei Algorithmen betrachten. Der Baker-Bird-Algorithmus markiert unter Verwendung des Aho-Corasick-Algorithmus die Vorkommen der Spaltenw¨orter. Anschließend wird unter Verwendung des KMP-Algorithmus zeilenweise nach den Vorkommen der Spaltenw¨orter in der korrekten Reihenfolge gesucht. Der Amir-Banson-Farach-Algorithmus ermittelt ¨ahnlich dem Duell-Algorithmus von Vis- hkin eine Kandidatenmenge von paarweise vertr¨aglichen Kandidaten und pruft¨ in linearer Zeit, ob an diesen Stellen das gesuchte Bild tats¨achlich vorkommt. Der Zhu-Takaoka-Algorithmus ermittelt ¨ahnlich dem Karp-Rabin-Algorithmus mit Hilfe von Fingerabdrucken¨ Kandidaten fur¨ ein Vorkommen des gesuchten Bildes. Da bei Bildern das Alphabet Σ (Farbwerte) in der regel sehr groß ist, betrachten wir bei den Algorithmen den Einfluß der Alphabetgr¨oße Σ auf die Laufzeit.

Baker-Bird-Algorithmus

Wir sehen ein Bild P der Gr¨oße (m1, m2) als Vektor von m2 Spaltenw¨orter (P1,P2,...,Pm2 ) der L¨ange m1 an. Es seien Q1,Q2,...,Qr die paarweise verschiedenen Spaltenw¨orter, die in

P vorkommen. Dann gilt Pi = Qti fur¨ geeignete ti ∈ {1, . . . , r} und alle 1 ≤ i ≤ m2, und

P kann mit dem Vektor (t1, t2, . . . , tm2 ) der Indizes der in P vorkommenden verschiedenen Spaltenw¨orter identifiziert werden. Der Baker-Bird-Algorithmus konstruiert man den Aho-Corasick-Baum fur¨ die Menge C = {Q1,Q2,...,Qr}. Anschließend wird in jeder Spalte von T nach der Menge C gesucht.

44 Endet an einer Stelle ein Vorkommen eines Wortes Qt, so schreiben wir an diese Stelle ein t; anderenfalls eine 0. In dem so erhaltenen Bild T 0 uber¨ {0, 1, . . . , r} sucht man schließlich zeilenweise nach Vorkommen des Wortes t1t2 ··· tm2 . Wird das Wort an Stelle j2 der Zeile j1 gefunden, so kommt P in T an der Stelle (j1 − m1 + 1, j2) vor.

Beispiel 2.5 Fur¨ die Bilder P und T liefert die Aho-Corasick-Suche nach den W¨ortern {abb, baa} in den Spalten von T das Zwischenergebnis T 0. T : b b b a a a b a a a b a T 0: 0 0 0 0 0 0 0 0 0 0 0 0 b a a b a b b a b a a a 0 0 0 0 0 0 0 0 0 0 0 0 a b a a a b b a b a b b 0 2 0 0 0 1 0 0 1 0 2 0 b a b a b a a b a b a b 2 0 0 0 0 0 0 0 0 0 0 1 P : a b a a b b a b a a b b b a a 0 2 1 0 1 0 0 1 2 1 0 0 b a b a a a a a a b a a a a b 0 0 0 0 0 0 0 0 0 0 0 2 b b b b a a b b a a a b a b a 0 0 0 0 2 0 0 0 0 0 0 0 Die Suche nach dem Wort 121 in den Zeilen von T 0 liefert dann das Vorkommen (3, 8) von P in T .

Satz 2.4 Der Baker-Bird-Algorithmus findet die Vorkommen von P in T mit einem Aufwand von Θ(N log σ) fur¨ die Suche. Die Abh¨angigkeit der Laufzeit von der Alphabetgr¨oße ist problematisch, da die Alphabete (Farbwerte) bei Bildern h¨aufig sehr groß sind. In der hier gew¨ahlten Darstellung ben¨otigt man 0 fur¨ T einen zus¨atzlichen Platz von Θ(n1n2); dieser kann aber auf Θ(m1m2) bei asymptotisch gleicher Laufzeit beschr¨ankt werden.

Zhu-Takaoka-Algorithmus

Wir gehen wieder davon aus, daß das gesuchte Bild P aus den Spaltenw¨ortern P1,P2,...,Pm2 besteht. Im Pr¨aprozessing bestimmen wir eine zuf¨allige Primzahl q und bilden die aus dem Karp- Rabin-Algorithmus (Abschnitt 1.10) bekannten Werte hi = Hashq(Pi), 1 ≤ i ≤ m2. In der ersten Suchphase bestimmen wir die Hash-Werte der Spaltenw¨orter von T und speichern sie in einem Bild T 0 uber¨ dem Alphabet {0, 1, . . . , q − 1}. In der zweiten Suchphase bestimmen wir in T 0 mittels des KMP-Algorithmus die Vor-

kommen von h1h2 . . . hm2 . Nur an diesen Stellen kann (muß aber nicht) das gesuchte Bild P vorkommen.

Satz 2.5 Der Zhu-Takaoka-Algorithmus ermittelt in einer Zeit von Θ(N) Kandidaten fur¨ das Vorkommen von P in T .

Bezuglich¨ der m¨oglichen Varianten der Implementierung gilt das zum Karp-Rabin-Algorithmus Gesagte.

Beispiel 2.6 Fur¨ die Bilder P und T uber¨ Σ erhalten wir bei der Wahl q = 17 fur¨ P die Hash-Werte (1, 15, 6) und das Zwischenergebnis T 0 der Hash-Werte von T .

45 T : 0 1 1 0 0 8 0 2 9 5 1 0 T 0: 5 3 7 2 0 1 9 2 1 3 0 2 0 0 6 2 1 5 7 8 0 9 2 8 16 11 6 5 1 16 12 7 9 12 0 11 2 4 2 3 2 4 0 8 3 8 4 7 9 15 14 2 12 1 1 16 1 7 7 15 P : 1 5 7 3 2 9 6 0 2 3 6 2 6 4 4 6 8 0 15 1 15 6 2 15 0 6 7 2 4 0 8 6 3 4 2 0 4 5 4 4 5 4 0 1 4 7 15 12 0 15 1 14 3 13 0 2 3 4 7 0 4 4 3 4 2 4 1 3 6 10 12 12 15 7 16 4 6 6 12 11 4 Die Suche nach dem Wort (1, 15, 6) in den Zeilen von T 0 liefert dann den Kandidaten (3, 5) von P in T , der auch tats¨achlich ein Vorkommen ist.

Amir-Banson-Farach-Algorithmus Die Begriffe der Periode sowie der Vertr¨aglichkeit lassen sich auf zweidimensionale Bilder verallgemeinern.

Definition 2.5 Es sei P ein Bild der Gr¨oße (m1, m2). Ein Paar (p1, p2) 6= (0, 0) mit 0 ≤ |p1| ≤ m1, 0 ≤ p2 ≤ m2 heißt Periode von P , wenn P [i1, i2] = P [i1 + p1, i2 + p2] fur¨ alle (i1, i2) gilt.

Ist (p1, p2) mit 0 ≤ |p1| ≤ m1, 0 ≤ p2 ≤ m2 keine Periode, so existiert ein Wert (z1, z2) mit P [z1 + 1, z2 + 1] 6= P [z1 + p1 + 1, z2 + p2 + 1]. Dieser Wert (z1, z2) ist dann ein Zeuge dafur,¨ daß (p1, p2) keine Periode ist.

Definition 2.6 Es sei P ein Bild der Gr¨oße (m1, m2).Fur¨ ein Paar (p1, p2) 6= (0, 0) mit

0 ≤ |p1| ≤ m1, 0 ≤ p2 ≤ m2 definieren wir Z(p1,p2)(P ) als (m1 + 1, m2 + 1), falls (p1, p2) eine Periode von P ist, bzw. als min min{P [z1 + 1, z2 + 1] 6= P [z1 + p1 + 1, z2 + p2 + 1]} , falls p1 ≥ 0 und (p1, p2) keine Periode z2 z1 min max{P [z1 + 1, z2 + 1] 6= P [z1 + p1 + 1, z2 + p2 + 1]} , falls p1 < 0 und (p1, p2) keine Periode z2 z1

Beispiel 2.7 Das unten angegebene Bild P hat u.a. die Perioden (1, 2) und (−2, 2). Das Paar (−1, 1) ist keine Periode; es gilt Z(−1,0) = (2, 2). a b b a b a a b a b b a P : a b b a a b b a a b b a b a a b ab a b b a a b b a a b b a b a a b b ab a b a b a b a b a b a a b b a b a b a b a b a b a

Ohne Beweis geben wir das folgende Resultat fur¨ das Pr¨aprozessing an. Der Beweis kann in der Originalarbeit von Amir, Benson und Farach nachgelesen werden. Insbesondere wird Ge- brauch von Suffixb¨aumen und LCA-Bestimmungen in konstanter Zeit gemacht; diese Themen werden in einem sp¨ateren Kapitel der Vorlesung noch angesprochen.

Lemma 2.6 Fur¨ ein Bild P der Gr¨oße (m1, m2) sind die Werte Z(p1,p2) fur¨ 0 ≤ |p1| ≤ m1, 0 ≤ p2 ≤ m2 mit einem Aufwand von O(m1m2 logσ) berechenbar.

46 Definition 2.7 Es sei P ein Bild der Gr¨oße (m1, m2). Zwei Paare naturlicher¨ Zahlen j = (j1, j2) und k = (k1, k2) mit j2 ≤ k2 heißen vertr¨aglich bezuglich¨ P , wenn es ein Bild T gibt, das sowohl an der Stelle j als auch an der Stelle k ein Vorkommen von P enth¨alt. Gilt zus¨atzlich j1 ≤ k1, so heißen j und k abw¨arts vertr¨aglich; gilt zus¨atzlich j1 ≥ k1, so heißen j und k aufw¨arts vertr¨aglich. Ahnlich¨ wie im eindimensionalen Fall k¨onnen wir formulieren:

Folgerung 2.7 Es sei P ein Wort mit |P | = m. Zwei Positionen (j1, j2) und (k1, k2) mit j2 < k2 sind genau dann vertr¨aglich bezuglich¨ P , wenn (k1 − j1, k2 − j2) eine Periode von P |k1 − j1| > m1 oder k2 − j2 > m2 ist.

Lemma 2.8 Sind (j1, j2) und (k1, k2) mit j2 ≤ k2 sowie (k1, k2) und (l1, l2) mit k2 ≤ l2 jeweils abw¨arts vertr¨aglich bezuglich¨ P , so sind auch (j1, j2) und (l1, l2) abw¨arts vertr¨aglich bezuglich¨ P . Sind (j1, j2) und (k1, k2) mit j2 ≤ k2 sowie (k1, k2) und (l1, l2) mit k2 ≤ l2 jeweils aufw¨arts vertr¨aglich bezuglich¨ P , so sind auch (j1, j2) und (l1, l2) aufw¨arts vertr¨aglich bezuglich¨ P .

Sind zwei Positionen (j1, j2) und (k1, k2) nicht vertr¨aglich, so gilt P [z1 + 1, z2 + 1] 6=

P [z1 +p1 +1, z2 +p2 +1] fur¨ (p1, p2) = (k1, k2)−(j1, j2), (z1, z2) = Zp1,p2 (P ). Man kann damit die Prozedur Duell aus dem Algorithmus von Vishkin (siehe Seite 26) im eindimensionalen Fall verallgemeinern, um eine von zwei unvertr¨aglichen Positionen auszuschließen. Wie der Algorithmus von Vishkin l¨auft der Algorithmus von Amir, Benson und Farach in zwei Phasen ab.

1. Man ermittelt eine Menge C von paarweise vertr¨aglichen Kandidaten fur¨ Vorkommen von P in T .

2. Man testet in O(N) Schritten, ob die Kandidaten tats¨achlich Vorkommen sind.

1. Phase. Als erstes bestimmt man fur¨ jede Spalte j mit 1 ≤ j ≤ n2 eine Menge Spj von paarweise vertr¨aglichen Positionen. Diese Mengen speichert man jeweils als Stack, wobei die Position mit der kleinsten Zeilennummer die unterste ist. Die Konstruktion eines Stacks ist unter Verwendung von Duellen mit einem Aufwand von O(n1) m¨oglich. Danach bestimmt man eine Menge Cab von paarweise abw¨arts vertr¨aglichen Positionen. Dazu wird fur¨ jede Zeile i ein Stack Zei angelegt. Zu jedem Zeitpunkt ist jedes Element (i, j) aus einem Stack Zei mit jedem von (i, j) aus rechts unten befindlichem Element aus den Zeilenstacks vertr¨aglich. Dabei geht man in den Spalten von rechts nach links und testet in- nerhalb einer Spalte nacheinander die Kandidaten aus Spj auf Vertr¨aglichkeit. Wir betrachten das Vorgehen fur¨ einen Kandidaten (i, j) genauer. Um (i, j) aufnehmen zu k¨onnen, muß diese Position vertr¨aglich mit jedem der Stacks Zei0 0 fur¨ i ≤ i < i + m1 sein. Wegen Lemma 2.8 braucht man nur die Vertr¨aglichkeit mit den jeweiligen Stackspitzen zu garantieren. Die Anzahl der notwendigen Vergleiche kann wie folgt weiter reduziert werden. Es sei r die oberste Zeile, mit der der Vorg¨anger von (i, j) in Spj vertr¨aglich war (falls (i, j) das erste Element in Spj ist, setzen wir r = n1 + 1). Erneut folgt aus Lemma 2.8, daß (i, j) mit allen Zeilen ab Zeile r vertr¨aglich ist. Man geht also derart vor, daß man fur¨ die Zeilen von min{r, i + m1} − 1 abw¨arts bis zur Zeile i testet, ob die Position (i, j) mit der Spitze des entsprechenden Zeilenstacks vertr¨aglich

47 ist. Stellt man eine Unvertr¨aglichkeit fest, so fuhrt¨ man ein Duell aus, in dessen Ergebnis entweder der neue Kandidat oder die Stackspitze ausscheidet. Der Unterlegene des Duells wird aus seinem Spaltenstack und seinem Zeilenstack gestrichen. Uberlebt¨ der Kandidat (i, j) alle Duelle, so ist (i, j) vertr¨aglich mit allen Positionen rechts unten von sich; (i, j) verbleibt in Spj und wird Spitze des Stacks Zei. In jedem Fall aktualisiert man den Wert r der obersten vertr¨aglichen Zeile. Anschließend gewinnt man, beginnend mit den neuen Spaltenstacks Spj, in analoger Weise eine Menge C, die aufw¨arts vertr¨aglich ist. Da zu Beginn dieser Konstruktion die Positionen in den Spaltenstacks abw¨arts vertr¨aglich waren, sind am Ende alle Positionen paarweise ver- tr¨aglich. Die Laufzeit ist proportional zur Zahl der Tests auf Vertr¨aglichkeit. Fur¨ jeden Zeilenstack wird pro Spalte h¨ochstens einmal Vertr¨aglichkeit festgestellt; insgesamt wird also h¨ochstens n1n2-mal Vertr¨aglichkeit registriert. Bei Unvertr¨aglichkeit scheidet eine Position aus. Da- mit wird h¨ochstens n1n2-mal Unvertr¨aglichkeit festgestellt. Insgesamt ist die Laufzeit also O(n1n2) = O(N).

2. Phase Nun geht es darum, die Kandidaten zu testen. Erneut wird dabei so vorgegan- gen, daß jede Position des Bildes nur bezuglich¨ eines m¨oglichen Kandidaten getestet werden muß. Dazu bestimmen wir fur¨ jede Position (i, j) die Position R[i, j] die von den rechtesten Positionen, in deren Einflußbereich (i, j) liegt, die unterste ist, formal:

R[i, j] = max max{(z, s) ∈ C : i − m1 < z ≤ i, j − m2 < s ≤ j} z s wobei wir max ∅ := (0, 0) definieren. Die Werte R[i, j] k¨onnen mittels Dynamischer Program- mierung mit einem Aufwand von O(N) bestimmt werden. Sie ergeben sich wie folgt.

R[i, 0] = (0, 0) fur¨ 1 ≤ j ≤ n2

R[0, j] = (0, 0) fur¨ 1 ≤ i ≤ n1 ( (i, j), falls (i, j) ∈ C, R[i, j] = max max{(z, s) ∈ {R[i − 1, j],R[i, j − 1]} : i − m1 < z ≤ i, j − m2 < s ≤ j}, sonst. z s

Sei R[i, j] = (x, y). Gilt (x, y) 6= (0, 0) und T [i, j] = P [i−x+1, j −y+1], so ist die Position (i, j) korrekt fur¨ alle Kandidaten, in deren Einflußbereich (i, j) liegt; wir setzen T 0[i, j] = 1. Anderenfalls ist (i, j) inkorrekt fur¨ alle Kandidaten, in deren Einflußbereich (i, j) liegt; wir setzen T 0[i, j] = 0. Dann kommt P genau dann an einer Position (x, y) des Bildes T vor, wenn 0 an der Position (x, y) des Bildes T ein Vorkommen des Bildes der Gr¨ose (m1, m2), das nur aus Einsen besteht vorliegt. Die Suche nach diesem Bild kann mit einem Aufwand von O(N), z.B. unter Anwendung des Baker-Bird-Algorithmus, erfolgen.

2.3 Suche nach regul¨aren Ausdrucken¨

Der Vollst¨andigkeit halber geben wir zuerst die Definition regul¨arer Ausdrucke¨ und ihrer Sprachen sowie die Konstruktion von Thompson zur Erzeugung eines ¨aquivalenten NEA an.

48 Definition 2.8 Es sei Σ ein Alphabet. Die Menge der regul¨aren Ausdrucke¨ uber¨ Σ ist wie folgt definiert: 1. ∅, ε, a fur¨ a ∈ Σ sind regul¨are Ausdrucke.¨

2. Sind α und β regul¨are Ausdrucke,¨ so sind auch (α | β), αβ und (α)∗ regul¨are Ausdrucke.¨

3. Andere regul¨are Ausdrucke¨ gibt es nicht.

Definition 2.9 Die von einem regul¨aren Ausdruck γ erzeugte Sprache L(γ) ist wie folgt induktiv definiert: 1. L(∅) = ∅, L(ε) = {ε}, L(a) = {a} fur¨ a ∈ Σ. 2. L((α | β)) = L(α) ∪ L(β), L(αβ) = L(α)L(β), L((α)∗) = (L(α))∗.

Satz 2.9 Fur¨ jeden regul¨aren Ausdruck der L¨ange m existiert ein ¨aquivalenter NEA mit O(m) Zust¨anden und O(m) Transitionen. Der Beweis des Satzes erfolgt durch die folgende bekannte Konstruktion von Thompson. Diese Konstruktion erzeugt induktiv fur¨ jeden regul¨aren Ausdruck einen NEA. Dieser NEA besitzt genau einen Anfangszustand und einen akzeptierenden Zustand. Wir skizzieren diese Konstruktion graphisch. Eine genauere Besprechung und einen Korrektheitsbeweis findet man z.B. in [8].

1. Fur¨ die Ausdrucke¨ ∅, ε und a ergeben sich folgende NFA: • ∅: -  jε j • ε: - -  - ja- j • a:   j j 2. Sind die NEA fur¨  α bzw. β - − α + bzw. - − β + , so ergeben sich folgende   NEA. j j j j   α ε1− + PPPε  Pq - j j • (α | β): P PP 1 j ε Pq− β +  ε j  j j

• αβ: - ε- − α + ε- − β + ε -  j j j j j j  ε

• (α)∗: - ε- − α + ε -  j j j j Offensichtlich kann man die Frage, ob ein gegebenes Wort w zur Sprache des regul¨aren Ausdruck α geh¨ort, mit Hilfe des NEA entscheiden. Wir wollen uns mit dem allgemeineren Problem befassen, Vorkommen eines regul¨aren Ausdruck α in einem Text T zu finden.

49 Definition 2.10 Es seien T ein Text der L¨ange n und α ein regul¨arer Ausdruck. Ein Intervall [j, k] mit 1 ≤ j ≤ k ≤ n heißt Vorkommen von α in T , wenn T [j . . . k] ∈ L(α) gilt.

Gegeben seien nun ein Text T der L¨ange n und ein regul¨arer Ausdruck der L¨ange m. Gesucht sind Vorkommen von α in T . Der wesentliche Unterschied zu den bisher betrachteten Problemen ist, daß ein Vorkommen von α keine feste L¨ange besitzt. Es kann insbesondere Θ(n2) Treffer in T geben. Deshalb beschr¨ankt man sich bei den meisten Implementierungen darauf, ausgew¨ahlte Vorkommen anzugeben. In der Regel wird ein Vorkommen angegeben, das so weit links wie m¨oglich beginnt. Da der Text an den Vorkommen der Treffer h¨aufig modifiziert werden soll, sucht man oft nur nach nicht-uberlappenden¨ Vorkommen. Die Konstruktion des zu Σ∗α ¨aquivalenten NEA ist die Grundlage fur¨ alle Algorithmen zur Suche nach regul¨aren Ausdrucken.¨ Fur¨ die weitere Verwendung des NEA gibt es verschiedene M¨oglichkeiten:

1. Konstruktion des ¨aquivalenten DEA und Nutzung des DEA fur¨ die Suche. Dies ist eine effiziente Methode fur¨ kurze Ausdrucke.¨ Der Nachteil dieser Methode ist die m¨oglicher- weise exponentielle Gr¨oße des DEA.

2. Suche nach einem akzeptierenden Pfad im NEA durch Backtracking. Auch diese Me- thode ist verbreitet (z.B. Perl) und hat den Vorteil, zu einem Treffer gleich einen Pfad zu liefern. Der akzeptierende Pfad wird n¨amlich ben¨otigt, um Treffer fur¨ eventuell gewunschte¨ Teilausdrucke¨ zu finden. Der Nachteil dieser Methode ist die m¨oglicherweise exponentielle Laufzeit.

3. Bestimmung der nach jedem Textsymbol errichbaren Zust¨ande durch Dynamische Pro- grammierung. Diese Methode ermittelt in einer Laufzeit von O(mn) alle Textstellen, an denen ein Treffer fur¨ den Ausdruck endet. Um weitere Informationen zu erhalten (Beginn des Treffers, Auftreten von Teilausdrucken),¨ sind Modifikationen notwendig.

Wir wollen im folgenden ausfuhren,¨ wie man mit der letzten Methode alle maximalen Vorkommen von α mit einem Aufwand von O(mn) finden kann.

Definition 2.11 Es seien T ein Text der L¨ange n und α ein regul¨arer Ausdruck. Ein Vor- kommen [j, k] von α in T heißt

• rechts-maximal, wenn k0 ≤ k fur¨ alle Vorkommen [j, k0] gilt;

• links-maximal, wenn j0 ≥ j fur¨ alle Vorkommen [j0, k] gilt;

• maximal, wenn k0 < k oder j0 > j fur¨ alle anderen Vorkommen [j0, k0] gilt.

Es sei A = (Σ, Z, δ, {z0}, {zf }) der durch die Konstruktion von Thompson erhaltene NEA mit L(A) = L(α). Die Idee fur¨ die Bestimmung der links-maximalen Vorkommen besteht in der Berechnung der Mengen

∗ 0 ∗ 0 0 Z[k] := {(z, j): z ∈ δ (z0,T [j . . . k]) ∧ ∀j (z ∈ δ (z0,T [j . . . k]) → j ≥ j)}, 0 ≤ k ≤ n.

Das heißt, fur¨ (z, j) ∈ Z[k] ist der Zustand z mit einem Suffix von T [1 . . . k] erreichbar, und j ist der kleinste Index, so daß z mit T [j . . . k] erreichbar ist. Gilt (zf , j) ∈ Z[k], so endet an der Stelle k ein Vorkommen fur¨ α, und T [j . . . k] ist links-maximal.

50 Lemma 2.10 Mit den obigen Bezeichnungen gilt:

∗ Z[0] = {(z, 0) : z ∈ δ (z0, ε)},

Z[k] = {(z0, k)} ∪ 0 0 ∗ ∗  {(z, j): j = min {j : ∃y((y, j ) ∈ Z[k − 1] ∧ z ∈ δ (y, T [k]))} ∪ {k : z ∈ δ (z0, ε)} .

Insbesondere kann Z[k] aus Z[k − 1] mit einem Aufwand von O(m) berechnet werden. Beweis. Die Rekursionsbeziehung folgt aus der induktiven Definition von δ∗. Um die behaup- tete Laufzeit zu erreichen, gehen wir davon aus, daß Z[k−1] als geordnete Liste implementiert ist, wobei die Paare nach der 2. Komponente (aufsteigend) geordnet sind. Zur Bestimmung von Z[k] markieren wir zun¨achst alle Zust¨ande als nicht erreicht. Dann nehmen wir nachein- ander die Elemente (y, j) aus Z[k −1]. Fur¨ jedes z ∈ δ(y, T [k]) gehen wir folgendermaßen vor. Ist z als erreicht markiert, so brechen wir ab. Ist z noch nicht erreicht worden, so markieren wir z als erreicht, h¨angen (z, j) an die Liste Z[k] an und setzen die Prozedur rekursiv fur¨ alle Zust¨ande fort, die von z aus durch eine ε-Transition erreichbar sind. Ist die Liste Z[k − 1] ab- gearbeitet, so h¨angen wir noch (z0, k) an und durchsuchen noch die von z0 mit ε-Transitionen erreichbaren Zust¨ande. Da bei der Suche jede Transition h¨ochstens einmal durchlaufen wur- de und die Anzahl der Transitionen linear in m ist, folgt die Laufzeitabsch¨atzung. Offenbar sind die Paare in Z[k] wieder nach der zweiten Komponente geordnet, womit die behauptete Laufzeit fur¨ alle k per Induktion folgt. 2

Satz 2.11 Es sei T ein Text der L¨ange n und α ein regul¨arer Ausdruck der L¨ange m. Dann k¨onnen alle links-maximalen, alle rechts-maximalen und alle maximalen Vorkommen von α mit einem Aufwand von O(mn) bestimmt werden. Beweis. Daß alle links-maximalen Vorkommen mit einem Aufwand von O(mn) bestimmt werden k¨onnen, folgt aus dem obigen Lemma. Ein Vorkommen [j, k] von α in T ist rechts- maximal genau dann, wenn [n − k + 1, n − j + 1] ein links-maximales Vorkommen von αr in T r ist; dabei ist αr der regul¨are Ausdruck mit L(αr) = {w : wr ∈ L(α). Also k¨onnen auch die rechts-maximalen Vorkommen mit einem Aufwand von O(nm) gefunden werden. Ein Vorkommen [k, j] ist genau dann maximal, wenn es rechts-maximal ist und kein rechts- maximales Vorkommen [k0, j0] mit k0 < k, j0 ≥ j existiert. Aus den rechts-maximalen Vor- kommen kann man mit einem Aufwand von O(n) die maximalen Vorkommen bestimmen. 2

2.4 Einige Spezialf¨alle regul¨arer Ausdrucke¨

Fur¨ einige spezielle regul¨are Ausdrucke¨ besitzen die zugeh¨origen NEA eine sehr einfache Struktur, die den Einsatz von Bit-Parallelismus, ¨ahnlich zum Shift-And-Algorithmus oder BNDM-Algorithmus, erm¨oglicht.

Buchstabenklassen. Das Suchmuster P hat die Form P = S1S2 ··· Sm, wobei die Si Teilmengen von Σ sind. Anstelle einzelner Buchstaben stehen im Muster also Mengen von Buchstaben. Eine Textstelle gegenuber¨ einer Menge S muß mit einem Buchstaben aus S ubereinstimmen.¨

51 Fur¨ die Suche nach Mustern mit Buchstaben-Klassen sind die Algorithmen mit Bitarith- metik (Shift-And, BNDM) sehr einfach zu verallgemeinern. Man braucht n¨amlich nur die Bytes B[x] fur¨ die Zeichen aus Σ anzupassen. Im Byte B[x] wird das i-te Bit von rechts genau dann auf 1 gesetzt, wenn x ∈ Si gilt. Der Suchalgorithmus wird angewendet wie bei der Suche nach einem Wort.

Beispiel 2.8 Mit dem Muster P = ca{a, b}ac{b, c}b stimmen die W¨orter caaacbc, caaaccb, cabacbb und cabaccb uberein.¨ Es ergibt sich der folgende NEA:

- c- a - a, b- a- c - b, c- b- 0 1 2 3 4 5 6 7 m6 m m m m m m m Σ  ¦ ¥ Bei einer Byte-L¨ange von 8 ergeben sich die folgenden Bytes:

B[a] = 00111000,B[b] = 00010011,B[c] = 01000110.

Optionale und wiederholbare Symbole. Unser Suchmuster P kann jetzt aus Zeichen aus Σ sowie die Zeichenfolgen x?, x+ und x∗ mit x ∈ Σ, ?, +, ∗ ∈/ Σ enthalten. Die Interpretation der speziellen Folgen bedeutet: An der Stelle von x? kann x oder ε stehen; an der Stelle von x+ kann ein beliebiges Wort aus {x}+ stehen und an der Stelle von x∗ kann ein beliebiges Wort aus {x}∗ stehen. Wir nennen x? ein optionales x+ ein wiederholbares und x∗ ein optionales und wiederholbares Symbol. Wir betrachten hier nur das Problem, das Ende eines Vorkommens von P zu finden. Deshalb k¨onnen wir o.B.d.A. annehmen, daß das erste Symbol nicht optional ist. Der NEA fur¨ ein solches Suchmuster hat die gleiche Struktur wie der NEA fur¨ das Muster ohne Sonderzeichen. Außerdem gibt es fur¨ x? und x∗ eine ε-Kante parallel zur x-Kante sowie fur¨ x+ und x∗ eine x-Schleife am Zielknoten.

Beispiel 2.9 Fur¨ P = ab∗c?abb?a+ ergibt sich der folgende NEA: ε ε ε s s s - a- b- c- a- b- b- a- 0 1 2 3 4 5 6 7 m6 m m6 m m m m m6 Σ b a ¦ ¥ ¦ ¥ ¦ ¥ Es gibt u.a. folgende Treffer: aaba, abbbbcabbaaa, acabbaa.

Die einfache Struktur des NEA erm¨oglicht die Anwendung von Algorithmen mit Bit- Arithmetik. Wir beschreiben hier eine Erweiterung des Shift-And-Algorithmus. Wie beim Shift-And-Algorithmus wird die Menge der erreichbaren Zust¨ande in einem Byte Z gespei- chert. Im Pr¨aprozessing werden die Bytes B[x] wie beim Shift-And-Algorithmus ermittelt. Außerdem ben¨otigen wir weitere Bytes

• O fur¨ die Speicherung optionaler Symbole: Das i-te Bit von O ist genau dann 1, wenn das i-te Symbol optional ist.

• R fur¨ die Speicherung wiederholbarer Symbole: Das i-te Bit von R ist genau dann 1, wenn das i-te Symbol wiederholbar ist.

52 • I: fur¨ die Anf¨ange von ε-Pfaden: Das i-te Bit von I ist genau dann 1, wenn im Zustand i ein maximaler ε-Pfad beginnt.

• F : fur¨ die Enden von ε-Pfaden: Das i-te Bit von F ist genau dann 1, wenn im Zustand i ein maximaler ε-Pfad endet.

Die Aktualisierung geschieht fur¨ ein Textzeichen x in 3 Schritten:

1. Z ← (((Z<<1)|1) & B[x]) | (Z & B[x]& R) Damit werden alle Nachfolgezust¨ande ermittelt, die uber¨ eine x-Kante erreichbar sind

2. E ← Z | F Dies markiert alle Zust¨ande, die schon erreicht oder das Ende eines ε-Pfades sind.

3. Z ← Z | (O & ((˜(E − I))ˆE)) Das i-te Bit in (E −I) hat genau dann den gleichen Wert wie das i-te Bit in E, wenn der Zustand i entweder zu keinem ε-Pfad geh¨ort oder zu einem ε-Pfad geh¨ort und irgendein weiter links gelegener Zustand des selben ε-Pfades schon erreicht ist. Damit ergibt die Operation (O & ((˜(E − I))ˆE)) im i-ten Bit genau dann den Wert 1, wenn der Zustand i zu einem ε-Pfad geh¨ort und irgendein weiter links gelegener Zustand des selben ε-Pfades schon erreicht ist; das heißt, in Z haben am Ende alle Bits den Wert 1, wenn die zugeh¨origen Zust¨ande erreichbar sind.

Beispiel 2.10 In unserem Beispiel erhalten wir bei Byte-L¨ange 8: B[a] = 01001001, B[b] = 00110010, B[c] = 00000100, O = 00100110, R = 01000010, I = 00010001, F = 00100100.

Auch der Backward NDAWG-Algorithmus l¨aßt sich auf Suchmuster mit optionalen und wiederholbaren Zeichen verallgemeinern. In der Praxis liefert dies einen sehr effizienten Algo- rithmus, der von Navarro im Programm nrgrep implementiert wurde.

53 Kapitel 3

Inexakte Suche

3.1 Einleitung

Neben der exakten Suche hat in den letzten Jahren die inexakte Suche bzw. die Suche nach Ahnlichkeiten¨ an Bedeutung gewonnen. Im folgenden nennen wir einige Aufgabenstellungen sowie zugeh¨orige Anwendungen. 1. globale Ahnlichkeit:¨ Gesucht ist der “Abstand” zweier Zeichenketten, wobei eventuell die Unterschiede zu zeigen sind. Eine klassische Anwendung ist das Unix-Werkzeug diff, welches Unterschiede in Da- teien anzeigt. Dabei wird ubrigens¨ eine Zeile als ein Buchstabe betrachtet. 2. inexakte Suche: Gegeben sind ein Text T und ein Suchwort P . Gesucht sind die Teilw¨orter von T , die P hinreichend ¨ahnlich sind. Dies ist eine Erweiterung des In Kapitel 1 betrachteten Suchproblems. Da Schreibfeh- ler sowohl im Suchwort als auch im Text auftreten k¨onnen, ist diese Erweiterung sehr nutzlich¨ fur¨ die Suche in Datenbanken. 3. lokale Ahnlichkeit:¨ In zwei insgesamt sehr unterschiedlichen Zeichenketten sind Regionen mit hoher Ahnlichkeit¨ gesucht. Anwendungen findet man vor allem in molekularbiologischen Datenbanken. Funktionale Ahnlichkeit¨ unterschiedlicher Molekule¨ wird auf solche lokalen Sequenz¨ahnlichkeiten zuruckgef¨ uhrt.¨ H¨aufig wird das Problem der lokalen Ahnlichkeit¨ auch fur¨ mehr als zwei Zeichenketten untersucht. Bekanntestes Beispiel einer Abstandsfunktion fur¨ Zeichenketten beliebiger L¨ange ist der Leveshtein-Abstand. Er mißt die minimale Anzahl der elementaren Operationen • Ersetzen eines Zeichens durch ein anderes Zeichen, • L¨oschen eines Zeichens, • Einfugen¨ eines Zeichens, die man ben¨otigt, um eine Zeichenkette in eine andere zu uberf¨ uhren.¨ Um Ahnlichkeiten¨ bzw. Unterschiede zweier Zeichenketten darzustellen, verwendet man sogenannte Alignments (deutsch: Ausrichtungen). Im folgenden seien Σ ein Alphabet und ∈/ Σ ein Luckenzeichen.¨

54 ∗ 0 0 Definition 3.1 Es seien S1,S2 ∈ Σ . Ein Alignment von (S1,S2) ist ein Paar (S1,S2) mit 0 0 ∗ S1,S2 ∈ (Σ ∪ { }) , wobei 0 0 • S1 bzw. S2 aus S1 bzw. S2 durch Einfugen¨ von Luckenzeichen¨ entsteht, 0 0 • |S1| = |S2| gilt.

Beispiel 3.1 Es seien S1 = tempel und S2 = treppe. Es gibt u.a. folgende Alignments: t r e p p e t r e p p e t e m p e l t e m p e l Man kann ein Alignment als Darstellung einer Umwandlung mittels der oben genannten elementaren Operationen interpretieren. Stehen sich zwei unterschiedliche Zeichen aus Σ ge- genuber,¨ so wurde eine Ersetzung durchgefuhrt;¨ ein Zeichen aus Σ uber¨ einem entspricht einer L¨oschung, ein uber¨ einem Zeichen aus Σ entspricht einer Einfugung.¨ Im Beispiel ent- spricht das erste Alignment einer Umwandlung in 3 Schritten, das zweite Alignment einer Umwandlung in 4 Schritten. Das erste Alignment ist im Sinne des Levenshtein-Abstandes besser als das zweite. Allgemeiner definieren wir Bewertungen von Alignments wie folgt.

2 0 0 Definition 3.2 Es sei d : (Σ ∪ { }) → Z eine Bewertungsfunktion. Die Bewertung d(S1,S2) 0 0 0 0 eines Alignments (S1,S2) mit |S1| = |S2| = t ist

t 0 0 X 0 0 d(S1,S2) := d(S1[i],S2[i]). i=1 Im allgemeinen wird d eine symmetrische Funktion sein und d( , ) = 0 gelten. Die Inter- pretation von d h¨angt davon ab, ob man Unterschiede oder Ahnlichkeiten¨ sucht. Fur¨ den Levenshtein-Abstand zu bestimmen, benutzt man z.B. die Bewertungsfunktion d mit d(x, x) = 0 und d(x, y) = 1 fur¨ x 6= y. Gesucht ist hier ein Alignment mit minimaler Bewertung.

Die grundlegende Aufgabenstellung lautet also: Finde fur¨ zwei gegebene W¨orter ein opti- males Alignment. Außerdem betrachten wir folgende Varianten:

• Die Bewertungsfunktion wird so gew¨ahlt, daß die Bewertung eines Paares mit der Ahn-¨ lichkeit w¨achst. Gesucht ist dann das Alignment mit maximaler Bewertung. Ublich¨ sind solche Ahnlichkeitsbewertungen¨ bei Proteinen, wo die Ahnlichkeiten¨ von Aminos¨auren in deiner Tabelle (z.B. PAM, BLOSUM) angegeben werden.

• In einem Text T wird ein Teilwort gesucht, das einem Suchwort P ¨ahnlich ist (approxi- matives ).

• In zwei Zeichenketten S1, S2 werden Regionen großer Ahnlichkeit¨ gesucht (lokales Ali- gnment).

• Es sind nur solche optimalen Alignments gesucht, deren Bewertung unter einer gegebe- nen Schranke k liegt (Suche mit k Fehlern).

• Das Einfugen¨ bzw. L¨oschen wird als eine Operation angesehen und gesondert bewertet (Alignment mit Lucken¨ (gaps)).

55 3.2 L¨osung durch dynamische Programmierung

Zun¨achst wollen wir eine effiziente L¨osung des Grundproblems vorstellen. Dieses kann mit dynamischer Programmierung in quadratischer Zeit gel¨ost werden. Das Wesen der dynami- schen Programmierung ist, daß ein Problem gel¨ost wird, indem L¨osungen von Teilproblemen benutzt werden. Bestimmte triviale Teilprobleme werden direkt gel¨ost und dienen als Rekur- sionsbasis. Anschließend werden immer gr¨oßere Teilprobleme unter Verwendung der bereits erhaltenen Teill¨osungen gel¨ost. In unserem konkreten Problem bestimmen wir die optimalen Alignments der Pr¨afixe von S1 mit den Pr¨afixen von S2. Im folgenden gelte |S1| = m, |S2| = n.Fur¨ 0 ≤ i ≤ m, 0 ≤ j ≤ n sei Di,j(S1,S2) die Bewertung des optimalen Alignments der Pr¨afixe S1[1 . . . i] bzw. S2[1 . . . j]. Wie ublich,¨ schreiben wir einfach Di,j, wenn S1 und S2 aus dem Kontext klar sind. Außerdem schreiben wir di,j als Abkurzung¨ fur¨ d(S1[i],S2[j]). Um den Wert D(S1,S2) des optimalen Alignments von (S1,S2) zu finden, berechnen wir alle Werte Di,j und finden D(S1,S2) = Dm,n.

2 Satz 3.1 Es sei d : (Σ ∪ { }) → Z eine Bewertungsfunktion mit d( , ) = 0; und das Ali- gnment mit minimaler Bewertung sei gesucht. Dann gilt:

1. D0,0 = 0,

2. Di,0 = Di−1,0 + d(S1[i], ) fur¨ 0 < i ≤ m,

3. D0,j = D0,j−1 + d( ,S2[j]) fur¨ 0 < j ≤ n,

4. Di,j = min{Di−1,j−1 +d(S1[i],S2[j]),Di−1,j +d(S1[i], ),Di,j−1 +d( ,S2[j])} fur¨ 0 < i ≤ m, 0 < j ≤ n.

Beweis. Die Behauptungen (1),(2) und (3) sind offenbar korrekt, da es zwischen einem Wort α und dem leeren Wort genau ein Alignment gibt, welches den im Satz angegebenen Wert besitzt. Um (4) zu zeigen, betrachten wir ein Alignment (α, β) von (S1[1 . . . i],S2[1 . . . j]). Es seien x = S1(i), y = S2(j). Dann hat (α, β) eine der folgenden drei Formen:

(a) α = α1x, β = β1y Dann ist (α1, β1) ein Alignment von (S1[1 . . . i − 1],S2[1 . . . j − 1]).

(b) α = α2x, β = β2 Dann ist (α2, β2) ein Alignment von (S1[1 . . . i − 1],S2[1 . . . j]).

(c) α = α3 , β = β3y Dann ist (α3, β3) ein Alignment von (S1[1 . . . i],S2[1 . . . j − 1]).

Ist (α, β) zudem ein optimales Alignment von (S1[1 . . . i],S2[1 . . . j]), so gilt in den einzelnen F¨allen:

(a) Di,j = d(α, β) = d(α1, β1) + d(x, y) ≥ Di−1,j−1 + d(x, y),

(b) Di,j = d(α, β) = d(α2, β2) + d(x, ) ≥ Di−1,j + d(x, ),

(c) Di,j = d(α, β) = d(α3, β3) + d( , y) ≥ Di,j−1 + d( , y).

56 In jedem Fall haben wir Di,j ≥ min{Di−1,j−1 + d(x, y),Di−1,j + d(x, ),Di,j−1 + d( , y)}. Seien umgekehrt (α1, β1), (α2, β2) bzw. (α3, β3) die optimalen Alignments von (S1[1 . . . i− 1],S2[1 . . . j − 1]), (S1[1 . . . i − 1],S2[1 . . . j]), (S1[1 . . . i],S2[1 . . . j − 1]). Dann gilt

Di,j ≤ d(α1x, β1y) = d(α1, β1) + d(x, y)

Di,j ≤ d(α2x, β2 ) = d(α2, β2) + d(x, ) = Di−1,j + d(x, )

Di,j ≤ d(α3 , β3y) = d(α3, β3) + d( , y) = Di,j−1 + d( , y) und damit Di,j ≤ min{Di−1,j−1 + di,j,Di−1,j + d(x, ),Di,j−1 + d( , y)}. 2 Als unmittelbare Folgerung ergibt sich, daß die Bewertung des optimalen Alignments mit einem Zeitaufwand von O(mn) berechnet werden kann. Der Beweis gibt uns jedoch auch einen Algorithmus zur Bestimmung des optimalen Alignments, denn wir erhalten ein optimales Alignment von (S1[1 . . . i],S2[1 . . . j]) als Erweiterung eines optimalen Alignments von

• (S1[1 . . . i − 1],S2[1 . . . j − 1]), falls Di,j = Di−1,j−1 + d(S1[i],S2[j]),

• (S1[1 . . . i − 1],S2[1 . . . j]), falls Di,j = Di−1,j + d(S1[i], ),

• (S1[1 . . . i − 1],S2[1 . . . j − 1]), falls Di,j = Di,j−1 + d( ,S2[j]). Der Algorithmus kann am besten durch eine Tabelle mit den Zeilen 0, . . . , m und den Spalten 0, . . . , n veranschaulicht werden. Im Feld (i, j) werden der Wert Di,j und die Menge von Pointern Pi,j gespeichert. Die Pointer verweisen dabei auf die Felder, aus denen sich der Wert Di,j ergeben kann, d.h.

-∈ Pi,j ⇐⇒ Di,j = Di−1,j−1 + di,j,

↑∈ Pi,j ⇐⇒ Di,j = Di−1,j + 1,

←∈ Pi,j ⇐⇒ Di,j = Di,j−1 + 1.

Ein optimales Alignment kann man bestimmen, indem man den Pointern von (m, n) nach (0, 0) folgt. Insgesamt ergibt sich der Algorithmus 3.1, wobei die Zeilen 1 – 12 den Aufbau der Alignment-Tabelle und die Zeilen 13 – 21 die Ermittlung eines optimalen Alignments beinhalten.

57 Algorithmus 3.1 Ermittlung eines optimalen Alignments Eingabe: W¨orter S1,S2, |S1| = m, |S2| = n Ausgabe: optimales Alignment A von S1 und S2 (1) D0,0 ← 0; P0,0 ← ∅; (2) for i ← 1 to m (3) Di,0 ← Di−1,0 + 1; Pi,0 ← {↑}; (4) for j ← 1 to n (5) D0,j ← D0,j−1 + 1; P0,j ← {←}; (6) for i ← 1 to m (7) for j ← 1 to n (8) Di,j ← min{Di−1,j−1 + di,j,Di−1,j + 1,Di,j−1 + 1}; (9) Pi,j ← ∅; (10) if Di,j = Di−1,j−1 + di,j then Pi,j ← Pi,j ∪ {-}; (11) if Di,j = Di−1,j + 1 then Pi,j ← Pi,j ∪ {↑}; (12) if Di,j = Di,j−1 + 1 then Pi,j ← Pi,j ∪ {←}; (13) (i, j) ← (m, n); A ← (ε, ε); (14) while (i, j) 6= (0, 0) (15) p ← ein Pointer aus Pi,j; (16) if p =- then (17) A ← (S1(i),S2(j))A;(i, j) ← (i − 1, j − 1); (18) if p =↑ then (19) A ← (S1(i), )A;(i, j) ← (i − 1, j); (20) if p =← then (21) A ← ( ,S2(j))A;(i, j) ← (i, j − 1);

Beispiel 3.2 Fur¨ S1 = tempel und S2 = treppe ergibt sich bei Verwendung des Levenshtein- Abstandes folgende Alignment-Tabelle:

t r e p p e 0 ← 1 ← 2 ← 3 ← 4 ← 5 ← 6

t ↑ 1 - 0 ← 1 ← 2 ← 3 ← 4 ← 5

e ↑ 2 ↑ 1 - 1 - 1 ← 2 ← 3 - ← 4

m ↑ 3 ↑ 2 - ↑ 2 - ↑ 2 - 2 - ← 3 - ← 4

p ↑ 4 ↑ 3 - ↑ 3 - ↑ 3 - 2 - 2 ← 3

e ↑ 5 ↑ 4 - ↑ 4 - 3 ↑ 3 - ↑ 3 - 2

l ↑ 6 ↑ 5 - ↑ 5 ↑ 4 - ↑ 4 - ↑ 4 ↑ 3

t r e p p e und das einzige optimale Alignment t e m p e l

Satz 3.2 Es seien S1 und S2 W¨orter mit |S1| = m, |S2| = n. Algorithmus 3.1 bestimmt ein optimales Alignment von (S1,S2) mit einem Aufwand von O(mn).

Graphentheoretische Interpretation Das Problem des optimalen Alignments kann als graphentheoretisches Problem formuliert werden. Zu (S1,S2) mit |S1| = m, |S2| = n konstruieren wir den gerichteten Graphen G =

58 (U, E) mit

U = {(i, j) : 0 ≤ i ≤ m, 0 ≤ j ≤ n}, E = {((i − 1, j − 1), (i, j)) : 1 ≤ i ≤ m, 1 ≤ j ≤ n} ∪ {((i − 1, j), (i, j)) : 1 ≤ i ≤ m, 0 ≤ j ≤ n} ∪ {((i, j − 1), (i, j)) : 0 ≤ i ≤ m, 1 ≤ j ≤ n}

und der Kostenfunktion d : E → {0, 1} mit   d(S1[i],S2[j]), falls e = ((i − 1, j − 1), (i, j)) d(e) = d(S1[i], ), falls e = ((i − 1, j), (i, j))  d( ,S2[j]), falls e = ((i, j − 1), (i, j))

Die Knoten des Graphen sind die Felder unserer Tabelle, und jedes Feld hat Kanten zu seinen Nachbar rechts, unten sowie rechts unten (sofern die Nachbarn existieren). Ein Alignment entspricht einem gerichteten Pfad von s = (0, 0) nach t = (m, n). Damit ist das Alignment-Problem auf ein Kurzeste-Wege-Problem¨ zuruckgef¨ uhrt,¨ das wir z.B. auch mit dem Dijkstra-Algorithmus in O(mn) Schritten l¨osen k¨onnten. Unser Algorith- mus nutzt jedoch die besondere Struktur des Graphen aus. Dies wird bei einigen Varianten von Nutzen sein.

Ahnlichkeit¨ statt Abstand Will man Ahnlichkeit¨ messen d.h. die Alignment-Bewertung maximieren, so braucht man nur in der Rekursion das Minimum durch ein Maximum zu ersetzen. Ein wichtiger Spezialfall ist das Problem der l¨angsten gemeinsamen Teilfolge (longest common subsequence).

Definition 3.3 Eine gemeinsame Teilfolge von S1 und S2 ist ein Wort α mit S1 = β0α[1]β1 ··· α[t]βt 0 0 0 0 ∗ und S2 = β0α[1]β1 ··· α[t]βt fur¨ t = |α| und geeignete βi, βi ∈ Σ . Die l¨angste gemeinsame Teilfolge ist also ein Wort maximaler L¨ange, das mit Unterbre- chungen sowohl in S1 und S2 vorkommt. Die Bestimmung der l¨angsten gemeinsamen Teilfolge ist offenbar das Alignmentproblem fur¨ die Bewertungsfunktion v mit

 1, falls x = y und x, y ∈ Σ v(x, y) = 0, sonst

Die Matches in einem optimalen Alignment liefern eine maximale Teilfolge.

Approximatives Pattern Matching Wir betrachten die folgende Verallgemeinerung des Problems der Suche nach einem Muster in einem Text. Gesucht ist das optimale Alignment von S1 mit einem Teilwort von S2. Dieses Problem k¨onnen wir l¨osen, indem wir durch dynamische Programmierung fur¨ jedes Paar (i, j) das optimale Alignment von S1[1 . . . i] mit einem Suffix von S2[1 . . . j] bestimmen. Es sei (fur¨ ein Minimierungsproblem)

0 Di,j = min {D(S1[1 . . . i],S2[t . . . j])}. 0≤t≤j

59 0 0 0 Lemma 3.3 D0,0 = 0, D0,j = 0, Di,0 = i, 0 0 0 0 Di,j = min{Di−1,j−1 + d(S1[i],S2[j]),Di−1,j + d(S1[i], ),Di,j−1 + d( ,S2[j])} fur¨ 1 ≤ j ≤ n, 1 ≤ i ≤ m.

0 Beweis. D0,j = 0 gilt, da (ε, ε) das optimale Alignment von ε mit einem Suffix von T [1 . . . j] ist. Die Rekursionsbeziehung wird wie in Satz 3.1 bewiesen. 2 Das optimale approximative Matching kann ¨ahnlich bestimmt werden wie das optimale globale Alignment. Die Pointer werden ¨ahnlich gesetzt, nur daß die Felder der Zeile 0 keine Pointer enthalten. Ein optimales Alignment von S1 mit einem Suffix von S2[1 . . . j] findet man als einen Pfad von Feld (m, j) zu Zeile 0. Insgesamt k¨onnen wir feststellen:

Satz 3.4 Ein optimales approximatives Vorkommen von S1 in S2 (einschließlich einem op- timalen Alignment) kann mit einem Aufwand von O(mn) gefunden werden.

Lokale Alignments

Definition 3.4 Ein lokales Alignment von (S1,S2) ist ein Alignment von (α, β), wobei α bzw. β Infixe von S1 bzw. S2 sind. Lokale Alignments sollten durch Ahnlichkeitsfunktionen¨ (mit positiven Bewertungen als Zeichen der Ahnlichkeit)¨ bewertet werden, da man bei einer Abstandsfunktion das triviale lokale Alignment (ε, ε) als bestes lokales Alignment erhalten wurde.¨ Es seien also im folgenden ∗ 2 ¨ S1,S2 ∈ Σ mit |S1| = m, |S2| = n und d : (Σ ∪ { }) → Z eine Ahnlichkeitsfunktion. Fur¨ 00 0 ≤ i ≤ m, 0 ≤ j ≤ n sei Di,j die maximale Bewertung eines Alignments eines Suffixes von S1[1 . . . i] mit einem Suffix von S2[1 . . . j].

00 00 00 Lemma 3.5 D0,0 = Di,0 = D0,j = 0, 00 00 00 00 Di,j = max{Di−1,j−1 + d(S1(i),S2(j)),Di−1,j + d(S1(i), ),Di,j−1 + d( ,S2(j)), 0}, fur¨ 1 ≤ i ≤ m, 1 ≤ j ≤ n. Zur Bestimmung des optimalen lokalen Alignments gibt es nur zu sagen, daß Pointer 00 analog zum globalen Alignment gesetzt werden und im Falle von Di,j = 0 das Feld (i, j) keinen Pointer erh¨alt. Ein optimales lokales Alignment wird ermittelt, indem man von einem Feld mit maximalem D00-Wert den Pointern folgt, solange es geht. Im allgemeinen ist man jedoch nicht am Alignment mit maximaler Bewertung interessiert, sondern an lokalen Alignments mit einer gewissen Mindestbewertung.

Verkettung lokaler Alignments Die Konstruktion der lokalen Alignment-Tabelle liefert in der Regel eine große Menge von lokal optimalen Alignments. H¨aufig steht man vor der Aufgabe, ein globales Alignment zu konstruieren, das m¨oglichst viele gute Teilalignments enth¨alt. Dieses Problem ist zu l¨osen, indem man eine geeignete Menge von lokalen Alignments verkettet. Dabei k¨onnen zwei lokale Alignments von (S1[i1 . . . i2],S2[j1 . . . j2]) und (S1[i3 . . . i4],S2[j3 . . . j4]) genau dann verketten, wenn i2 < i3 und j2 < j3 gilt. Gesucht ist also eine Kette von Alignments

C = (S1[i1 . . . i2],S2[j1 . . . j2]); (S1[i3 . . . i4],S2[j3 . . . j4]); ... (S1[i2r−1 . . . i2r],S2[j2r−1 . . . j2r])

60 mit i1 < i2 < i3 < i4 < . . . < i2r−1 < i2r und j1 < j2 < j3 < j4 < . . . < j2r−1 < j2r, so daß

r X d(S1[i2t−1 . . . i2t],S2[j2t−1 . . . j2t]) → max . t=1

Die geometrische Interpretation ist wie folgt: Ein lokales Alignment von S1[i1 . . . i2] und S2[j1 . . . j2] entspricht dem achsenparallelen Rechteck [i1, i2] × [j1, j2]. Zwei lokale Alignments k¨onnen genau dann miteinander verkettet werden, wenn die rechte untere Ecke des ersten Rechtecks links oben von der linken oberen Ecke des zweiten Rechtecks liegt. Gegeben ist also eine Menge von Rechtecken mit Bewertungen, und gesucht ist eine Kette von Rechtecken mit maximaler Summe der Bewertungen.

Definition 3.5 Es seien l, r ∈ IN mit l ≤ r. Das Intervall [l, r] ist [l, r] = {n : l ≤ n ≤ r}. Auf der Menge der Intervalle definieren wir die Halbordnung

Definition 3.6 Ein Rechteck ist das kartesische Produkt zweier Intervalle. Auf der Menge der Rechtecke definieren wir die Halbordnung

Definition 3.7 Es sei (M, <) eine Halbordnung. Eine (endliche) Kette in M ist eine Folge C = (c1, c2, . . . , cr) mit c1 < c2 < . . . < cr. Bevor wir das Verkettungsproblem fur¨ Rechtecke l¨osen, wollen wir ein analoges eindi- mensionales Problem, die Verkettung von Intervallen, betrachten. Gegeben sei eine endliche Menge R = {[l1, r1], [l2, r2],..., [ls, rs]} von s Intervallen mit einer Bewertung d : R → IN. Gesucht ist eine Kette in R mit maximaler Bewertung. Die Idee des Algorithmus ist wie folgt. Wir ordnen zun¨achst die Endpunkte der Intervalle von links nach rechts. Dazu konstruieren wir ein Array X der L¨ange 2s. Jedes Element von X ist ein Paar der Form (j, x) mit j ∈ {1, . . . , s}, x ∈ {l, r}; dabei gibt j das Intervall an und x, ob es sich um einen linken oder einen rechten Endpunkt handelt. Geordnet sind die Elemente von X nach dem beschriebenen Punkt. Bei gleicher Zahl kommt ein linker Endpunkt vor einem rechten. Durch Dynamische Programmierung bestimmen wir fur¨ jedes Intervall aus R, die maximale Kette, die mit diesem Intervall endet.

Algorithmus 3.2 Verkettung von Intervallen Eingabe: Menge von Intervallen R = {[l1, r1], [l2, r2],..., [ls, rs]}, Bewertung d : {1, . . . , s} → IN, d(i) = d([li, ri]) Ausgabe: Bewertung der optimalen Kette in R (1) Bestimme das Array X der L¨ange 2s; (2) max ← 0; (3) for i ← 1 to 2s (4) (j, x) ← S[i]; (5) if x = l then D[j] ← d(j) + max; (6) if x = r then max ← max{max,D[j]}; (7) return max

61 Satz 3.6 Algorithmus 3.2 bestimmt die maximale Bewertung einer Kette in der Menge von Intervallen R mit einem Aufwand von O(s log s).

Beweis. Man zeigt durch Induktion, daß zu jedem Zeitpunkt max der gr¨oßte Wert einer bis zum aktuellen Punkt abgeschlossenen Kette und D[j] der gr¨oßte Wert einer mit dem Intervall [lj, rj] endenden Kette ist. Bezuglich¨ der Laufzeit ist zu sagen, daß die Sortierung der Intervallenden (Konstruktion von X) einen Aufwand von O(s log s) erfordert. Der Rest des Algorithmus l¨auft in einer Zeit von O(s) ab. 2 Wir wenden uns nun dem zweidimensionalen Problem zu. Gegeben sei jetzt eine endliche Menge R = {[l1, r1]×[o1, u1], [l2, r2]×[o2, u2],..., [ls, rs]×[os, us]} von s Rechtecken mit einer Bewertung d : R → IN. Gesucht ist eine Kette in R mit maximaler Bewertung. Erneut ordnen wir die linken und rechten Enden der Rechtecke (d.h. die Zahlen lj, rj) von links nach rechts und konstruieren ein Array X der L¨ange 2s wie im eindimensionalen Fall. Im Unterschied zum eindimensionalen Fall genugt¨ es nicht, eine Zahl max mit dem Wert der aktuell besten Verkettung mitzufuhren.¨ Stattdessen ben¨otigen wir eine Menge Max von Paaren (D, j) mit D ∈ IN, 1 ≤ j ≤ s. Ist in der Menge Max ein Paar (D, j) enthalten und ist in 0 0 der Menge X ein Endpunkt n abgeschlossen, so hat die beste Kette im Bereich [1, uj]×[1, n ] den Wert D und endet mit dem j-ten Rechteck. Die Elemente (D, j) von Max sind bezuglich¨ uj geordnet.

Algorithmus 3.3 Verkettung von Rechtecken

Eingabe: Menge von Rechtecken R = {[l1, r1]×[o1, u1], [l2, r2]×[o2, u2],..., [ls, rs]×[os, us]}, Bewertung d : {1, . . . , s} → IN, d(j) = d([lj, rj] × [oj, uj]) Ausgabe: Bewertung der optimalen Kette in R (1) Bestimme das Array X der L¨ange 2s; (2) Max ← {(0, 0)}; (3) for i ← 1 to 2s (4) (j, x) ← X[i]; (5) if x = l (6) (D, k) ← Element aus Max mit uk < oj und uk → max; (7) D[j] ← d(j) + D; (8) if x = r (9) (D, k) ← Element aus Max mit uk ≤ uj und uk → max; (10) if D < D[j] (11) Ordne (D[j], j) in Max ein; (12) (D, k) ← Element aus Max mit uk > uj und uk → min; (13) while D ≤ D[j] (14) L¨osche (D, k); (15) (D, k) ← Element aus Max mit uk > uj und uk → min; (16) (D, k) ← letztes Element von Max; (17) return D;

Satz 3.7 Algorithmus 3.3 bestimmt die maximale Bewertung einer Kette in der Menge von s Rechtecken R mit einem Aufwand von O(s log s).

62 Beweis. Fur¨ die Korrektheit zeigt man durch Induktion uber¨ i, daß die Menge Max tats¨achlich die vor dem Algorithmus angegebene Eigenschaft besitzt. Zur Laufzeit ist zu sagen, daß die Sortierung einen Aufwand von O(s log s) beansprucht. Der Aufwand fur¨ das Auffinden eines Elementes aus Max betr¨agt O(log s), ebenso der fur¨ das Einfugen¨ sowie das L¨oschen. Bis auf das Durchlaufen der while-Schleife betr¨agt der Aufwand fur¨ jedes Element aus X somit O(log s). Die gesamte Anzahl der Durchl¨aufe der while-Schleife entspricht der Anzahl der L¨oschungen aus Max, ist also durch s begrenzt unt kostet somit O(s log s) Schritte. 2

3.3 Alignments mit beschr¨ankter Fehlerzahl

Wir wollen jetzt nur Alignments in Betracht ziehen, deren Levenshtein-Bewertung durch eine Zahl k beschr¨ankt ist. Diese Beschr¨ankung erm¨oglicht fur¨ das globale Alignment und das approximative Pattern-Matching schnellere Algorithmen.

Globales Alignment

Gegeben sind eine naturliche¨ Zahl k sowie zwei Zeichenketten S1 und S2 mit |S1| = m, |S2| = n. Es gelte n − m = δ ≥ 0. Es ist zu entscheiden, ob der Levenshtein-Abstand von S1 und S2 durch k beschr¨ankt ist. Im positiven Fall ist ein optimales Alignment zu konstruieren.

Definition 3.8 Fur¨ eine Matrix mit den Zeilen 0, 1, . . . , m und den Spalten 0, 1, . . . , n ist die d-te Diagonale Diagd (−m ≤ d ≤ n) definiert als

Diagd = {(i, j) : 0 ≤ i ≤ m ∧ 0 ≤ j ≤ n ∧ j − i = d}.

Beispiel 3.3 In der folgenden Matrix sind die Diagonalen Diag−2 und Diag5 dargestellt.

0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6

Lemma 3.8 Besitzen S1 und S2 einen Levenshtein-Abstand von h¨ochstens k, so befindet sich der Pfad fur¨ das optimale Alignment innerhalb des Bereiches der Diagonalen Diagd mit −b(k − δ)/2c ≤ d ≤ b(k + δ)/2c. Beweis. Befindet sich ein Knoten (i, j) des Alignment-Graphen in der Diagonalen d = (j −i), so existieren von diesem Knoten Kanten zu den Diagonalen d − 1, d, d + 1. Die Kanten zu den Diagonalen d − 1 bzw. d + 1 haben ein Gewicht von 1. Der Startpunkt des Alignment-Pfades ist (0, 0), also auf der Diagonalen 0; der Endpunkt des Alignment-Pfades ist (m, n), also auf der Diagonalen δ. Seien nun −l ≤ 0 bzw. r ≥ δ die Diagonale mit dem niedrigsten bzw. h¨ochsten Index im Alignment-Pfad. Der Weg von (0, 0) zur Diagonalen −l kostet mindestens l; der von der

63 Diagonalen l nach (m, n) kostet mindestens l + δ. Die Gesamtkosten sind also mindestens 2l + δ. Wenn die Gesamtkosten h¨ochstens k betragen, so folgt l ≤ −b(k − δ)/2c. Analog zeigt man r ≤ b(k + δ)/2c. 2

Satz 3.9 Es kann mit einem Aufwand von O(km) ermittelt werden, ob der Levenshtein- Abstand von S1 und S2 durch k beschr¨ankt ist und im positiven Fall ein optimales Alignment bestimmt werden. Beweis. Man kann den Grundalgorithmus abwandeln, wobei nur nach Alignments im Be- reich der Diagonalen Diagd mit −b(k − δ)/2c ≤ d ≤ b(k + δ)/2c gesucht wird. (Die konkrete Abwandlung bleibt als Ubungsaufgabe).¨ In jeder Zeile sind h¨ochstens (k + 1) Werte zu be- stimmen, was einen Gesamtaufwand von O(km) ergibt. 2 Man kann den eben genannten Algorithmus auch benutzen, wenn keine Schranke gege- ben ist, um einen O(k∗m)-Algorithmus zu erhalten, wobei k∗ der Levenshtein-Abstand sei. Das heißt, fur¨ kleine Levenshtein-Abst¨ande erreicht man eine bessere Laufzeit als mit dem ursprunglichen¨ Algorithmus, w¨ahrend sie bei hohen Abst¨anden asymptotisch gleich bleibt.

∗ Satz 3.10 Das optimale Alignment von (S1,S2) kann mit einem Aufwand von O(k m) mit ∗ k = D(S1,S2) bestimmt werden. Beweis. Man setzt zun¨achst k ← 1. Solange es nicht gelingt, ein optimales Alignment mit einer Bewertung von h¨ochstens k zu bestimmen, verdoppelt man k. Die Gesamtlaufzeit ist beschr¨ankt durch log k∗ X ∗ c2im ≤ 2log k +1cm ≤ 2k∗cm. i=0 2

Approximatives Pattern Matching mit k Fehlern Gesucht sind die approximativen Vorkommen von P mit |P | = m in T mit |T | = n, deren Levenshtein-Bewertung durch k beschr¨ankt ist. Man kann den NEA zur Erkennung von P leicht in einen NEA zur Erkennung von P mit h¨ochstens k Fehlern erweitern. Der NEA zur Erkennung mit k Fehlern besteht aus (k + 1) Kopien des NEA zur Erkennung ohne Fehler. Den Einfugungen,¨ Ersetzungen und L¨oschungen entsprechen Transitionen aus der (j − 1)-ten in die j-te Kopie. Formal besitzt der NEA zur Erkennung von P = x1x2 ··· xm mit k Fehlern die Zustands- menge {0, 1, . . . , m} × {0, 1, . . . , k}, die Transitionenmenge

δ = {((0, 0), x, (0, 0)) : x ∈ Σ} ∪ {((i − 1, j), xi, (i, j)) : 1 ≤ i ≤ m, 0 ≤ j ≤ k} ∪ {((i, j − 1), x, (i, j)) : 0 ≤ i ≤ m, 1 ≤ j ≤ k, x ∈ Σ} ∪ {((i − 1, j), ε, (i, j)) : 0 ≤ i ≤ m, 1 ≤ j ≤ k} ∪ {((i − 1, j − 1), x, (i, j)) : 1 ≤ i ≤ m, 1 ≤ j ≤ k, x ∈ Σ},

den Startzustand (0, 0) und die Menge der Endzust¨ande {(m, j) : 0 ≤ j ≤ k}. Die Transitionen in den einzelnen Zeilen von δ erkl¨aren sich wie folgt.

64 1. Der Startzustand ist immer erreichbar, da an jeder Stelle ein approximatives Vorkommen von P beginnen k¨onnte; daher die Transition ((0, 0), x, (0, 0)). Wurde P [1 . . . i − 1] mit j Fehlern gefunden und stimmt P [i] mit dem aktuellen Text uberein,¨ so hat man nach dem n¨achsten Textsymbol ein Vorkommen von P [1 . . . i] mit j Fehlern; daher die Transitionen der Form ((i − 1, j), xi, (i, j)).

2. Wurde P [1 . . . i] mit j −1 Fehlern gefunden, so hat man nach dem n¨achsten Textsymbol ein Vorkommen von P [1 . . . i] mit j Fehlern (in T ist gegenuber¨ P ein Zeichen “ein- gefugt”);¨ daher die Transitionen der Form ((i, j − 1), x, (i, j)), x 6= xi. Die Bedingung x 6= xi kann man weglassen, da im Falle von x = xi auch der Zustand (i, j−1) erreichbar ist und die Erreichbarkeit von (i, j) keine Rolle fur¨ die Akzeptierung spielt.

3. Wurde P [1 . . . i − 1] mit j − 1 Fehlern gefunden, so hat man an der aktuellen Textstelle ein Vorkommen von P [1 . . . i] mit j Fehlern (ein Zeichen von P ist in T “gel¨oscht”); daher die Transitionen der Form ((i − 1, j − 1), ε, (i, j)).

4. Wurde P [1 . . . i−1] mit j −1 Fehlern gefunden und stimmt P [i] nicht mit dem aktuellen Text uberein,¨ so hat man nach dem n¨achsten Textsymbol ein Vorkommen von P [1 . . . i] mit j Fehlern; daher die Transitionen der Form ((i − 1, j − 1), x, (i, j)), x 6= xi. Die Bedingung x 6= xi kann man weglassen, da im Falle von x = xi auch der Zustand (i, j −1) erreichbar ist und die Erreichbarkeit von (i, j) keine Rolle fur¨ die Akzeptierung spielt.

Beispiel 3.4 Fur¨ P = abcabba und k = 2 ergibt sich der folgende NEA (Kanten ohne Beschriftung entsprechen Transitionen mit Symbolen aus Σ ∪ {ε}):

Σ ? - § ¤ a- b- c- a- b- b- a- j = 0 0 1 2 3 4 5 6 7 @ @ @ @ @ @ @ ΣΣΣΣΣΣΣΣm m m m m m m m @ @ @ @ @ @ @  ? @@R ? @@R ? @@R ? @@R ? @@R ? @@R ? @R ? - a- b- c- a- b- b- a- j = 1 0 1 2 3 4 5 6 7 @ @ @ @ @ @ @ ΣΣΣΣΣΣΣΣm m m m m m m m @ @ @ @ @ @ @  ? @@R ? @@R ? @@R ? @@R ? @@R ? @@R ? @R ? - a- b- c- a- b- b- a- j = 2 0 1 2 3 4 5 6 7 m m m m m m m m 

Fur¨ die Implementierung ben¨otigen wir die Bitvektoren B[x] wie gehabt fur¨ die Vorkom- 0 men der Symbole in P , Zj, 0 ≤ j ≤ k, fur¨ die alten Zust¨ande des NEA und Zj, 0 ≤ j ≤ k, fur¨ die neuen Zust¨ande des NEA. Ein Endzustand ist erreicht, wenn das m-te Bit in einem der Vektoren Zj gleich 1 ist.

Initialisierung: Zj ← (1<<(j − 1)), fur¨ 1 ≤ j ≤ k. Aktualisierung fur¨ Textsymbol x: 0 Z0 ← ((Z0<<1 | 1) & B[x]; 0 0 Zj ← (((Zj<<1 | 1) & B[x]) | Zj−1 | (Zj−1<<1) | (Zj−1<<1), fur¨ 1 ≤ j ≤ k; 0 Zj ← Zj, fur¨ 0 ≤ j ≤ k.

65 3.4 Alignments mit Lucken¨ (gaps)

0 0 Definition 3.9 Es sei (S1,S2) ein Alignment. Eine Lucke¨ (gap) ist eine maximale Folge von 0 0 Luckenzeichen¨ in S1 oder S2. 0 0 Jedes Alignment (S1,S2) ist eindeutig zerlegbar als 0 0 (S1,S2) = (α1, β1) ··· (αk, βk),

wobei, fur¨ 1 ≤ i ≤ k, αi und βi entweder kein Luckenzeichen¨ enthalten oder eins von beiden eine Lucke¨ ist. Die Abstandsfunktion d wird nur noch auf Σ × Σ definiert; außerdem gibt es eine Gap- Funktion g : IN+ → IR+, die eine Lucke¨ entsprechend ihrer L¨ange bewertet. Die Bewertung eines Alignments ergibt sich folgendermaßen:

|α| X d(α, β) := d(α[i], β[i]), falls α, β ∈ Σ∗ i=1 d(α, β) := g(|α|), falls α oder β Lucke¨ k 0 0 X d(S1,S2) := d(αj, βj), bei obiger Zerlegung j=1 √ Beispiel 3.5 Fur¨ die Gap-Funktion g(n) = n ergeben sich folgende Bewertungen fur¨ die Alignments von abaabb und aaba:

a b a a b b a b a a b b √ Bewertung: 3 Bewertung: 1 + 2 a a b a a a b a

Die Bestimmung des optimalen Alignments erfolgt wiederum durch dynamische Program- mierung. Fur¨ allgemeine Gap-Funktionen ist kubischer Aufwand n¨otig, w¨ahrend die Laufzeit im Falle affiner Gap-Funktionen quadratisch bleibt. Wir untersuchen die F¨alle im einzelnen.

Allgemeiner Fall

Die L¨ange eines Gaps am Ende eines Alignments (α, β) von (S1[1 . . . i],S2[1 . . . j]) ist begrenzt durch i, falls die Lucke¨ am Ende von β auftritt, und durch j, falls sich die Lucke¨ am Ende von α befindet. Fur¨ 0 ≤ i ≤ m, 0 ≤ j ≤ n und −j ≤ h ≤ i sei Di,j,h der Wert eines optimalen Alignments von (S1[1 . . . i],S2[1 . . . j]), das mit einem Gap der L¨ange |h| endet, wobei sich das Gap in S2 bzw. in S1 befindet, falls h > 0 bzw. h < 0 gilt. Weiterhin seien:

Di,j,+ := min{Di,j,h : 1 ≤ h ≤ i},

Di,j,− := min{Di,j,h : −j ≤ h ≤ −1}.

Fur¨ den Wert des optimalen Alignments von (S1[1 . . . i],S2[1 . . . j]) gilt offenbar: Di,j = min{Di,j,+,Di,j,−,Di,j,0}.

Satz 3.11 Im Falle einer beliebigen Gap-Funktion kann das optimale Alignment mit einem Aufwand von O(mn(m + n)) gefunden werden.

66 Beweis. Wir geben hier nur die Rekursionsformeln an und uberlassen¨ den Korrektheitsbeweis sowie die Konstruktion des optimalen Alignments als Ubungsaufgabe.¨ Fur¨ 0 ≤ i ≤ m und 0 ≤ j ≤ n gilt:

 g(j), falls h = −j  g(j), falls h = i D = D = 0,j,h ∞, sonst i,0,h ∞, sonst

Fur¨ 1 ≤ i ≤ m, 1 ≤ j ≤ n ergibt sich:

Di,j,0 = Di−1,j−1 + d(S1(i),S2(j))

Di,j,1 = min{Di−1,j,−,Di−1,j,0} + g(1)

Di,j,−1 = min{Di−1,j,+,Di−1,j,0} + g(1)

Di,j,h = Di−1,j,h−1 + g(h) − g(h − 1), 2 ≤ h ≤ i

Di,j,h = Di,j−1,h+1 + g(|h|) − g(|h| − 1), −j ≤ h ≤ −2 2

Affine Gap-Funktionen Wir betrachten jetzt eine Gap-Funktion der Form g(n) = a(n − 1) + b mit a, b ≤ 0. Derartige Bewertungen von Lucken¨ sind plausibel: es gibt eine Strafe b fur¨ das Er¨offnen einer Lucke¨ und eine Strafe a fur¨ das Vergr¨oßern einer Lucke¨ um 1. Fur¨ affine Gap-Funktionen l¨aßt sich das optimale Alignment mit quadratischem Aufwand finden, da sich die Berechnung der Werte Vi,j,+,Vi,j,−,Vi,j,0 vereinfacht.

Satz 3.12 Im Falle einer affinen Gap-Funktion kann das optimale Alignment mit einem Aufwand von O(mn) gefunden werden. Beweis. Wegen g(h + 1) − g(h) = a fur¨ h ≥ 1 ergeben sich folgende Beziehungen fur¨ 1 ≤ i ≤ m, 1 ≤ j ≤ n:

D0,0,0 = 0,D0,0,− = D0,0,+ = ∞

D0,j,− = a(j − 1) + b, D0,j,0 = D0,j,+ = ∞

Di,0,+ = a(i − 1) + b, Di,0,0 = Di,0,− = ∞

Di,j,0 = Di−1,j−1 + d(S1(i),S2(j))

Di,j,− = min{Di,j−1,0 + b, Di,j−1,+ + b, Di,j−1,− + a}

Di,j,+ = min{Di−1,j,0 + b, Di−1,j,− + b, Di−1,j,+ + a}

2 Realistischer als affine Gap-Funktionen erscheinen monoton wachsende konkave Funk- tionen, d.h. solche Funktionen g, fur die die Differenz g(n + 1) − g(n) monoton fallend ist √ ¨ (z.B. g(n) = n oder g(n) = log n). Die Kosten fur¨ eine Erweiterung der Lucke¨ werden dann mit wachsender Luckenl¨ ¨ange geringer. Ohne Beweis erw¨ahnen wir, daß fur¨ solche Gap- Funktionen das optimale Alignment mit einem Aufwand von O(mn log max{m, n}) bestimmt werden kann. Der sehr interessante Algorithmus ist im Abschnitt 12.6 des Buches von Gusfield zu finden.

67 3.5 L¨osung mit linearem Platzbedarf

Der bisher betrachtete Alignment-Algorithmus ben¨otigte eine Laufzeit von Θ(mn) und einen Speicherplatz von Θ(mn). Bei ublichen¨ Sequenzl¨angen von 105 ist bei der heutigen Technik die Laufzeit kein Problem, der Platzbedarf aber schon. Wir werden jetzt einen Algorithmus entwickeln, der mit linearem Platz auskommt und etwa die doppelte Laufzeit ben¨otigt. Die Bewertung des optimalen Alignments kann sehr einfach mit linearem Platz bestimmt werden, da man fur¨ die Bestimmung einer Zeile i der Alignment-Tabelle nur die Zeile i − 1 ben¨otigt. Um auch das optimale Alignment mit linearem Platzbedarf zu ermitteln, verfolgen wir eine Teile-und-herrsche-Strategie. Der Pointer in einem Tabellenfeld verweist jetzt nicht mehr auf den direkten Vorg¨anger, sondern gibt an, auf welche Weise der optimale Pfad zum Feld die Mittellinie von Zeile bm/2c nach Zeile bm/2c + 1 uberquerte.¨ Wir k¨onnen folgenden rekursiven Algorithmus entwickeln:

Algorithmus 3.4 Alignment-Rekursiv (Hirschberg) Eingabe: W¨orter S1, S2, Grenzen m1 ≤ m2, n1 ≤ n2 Ausgabe: Optimaler Alignment-Pfad von (m1, n1) nach (m2, n2) Aufruf: AR((m1, n1), (m2, n2)) (1) if m1 = m2 then (2) return (m1, n1) → (m1, n1 + 1) → · · · → (m1, n2 − 1) → (m1, n2); (3) if n1 = n2 then (4) return (m1, n1) → (m1 + 1, n1) → · · · → (m2 − 1, n1) → (m2, n1); 0 m1+m2 (5) m ← b 2 c; (6) Bestimme die Kante (m0, j) → (m0 + 1, j0) im optimalen Alignment-Pfad von (m1, n1) nach (m2, n2); 0 (7) P1 ← AR((m1, n1), (m , j)); 0 0 (8) P2 ← AR((m + 1, j ), (m2, n2)); P1 0 0 0 P2 (9) return (m1, n1) → (m , j) → (m + 1, j ) → (m2, n2);

Satz 3.13 Die Bestimmung eines optimalen Alignments kann mit einem Platzbedarf von O(m + n) in einer Zeit von O(mn) erfolgen.

Beweis. Fur¨ bm/2c + 1 ≤ i ≤ m, 0 ≤ j ≤ n sei Ki,j die Kante eines optimalen Alignment- Pfades von (0, 0) nach (i, j), die von Zeile bm/2c nach Zeile bm/2c + 1 fuhrt.¨ Dabei notieren wir eine Kante Ki,j durch die Ausgangsspalte und die Richtung, d.h. wir schreiben (t, &) m m m m anstelle von ((b 2 c, t), (b 2 c + 1, t + 1)) und (t, ↓) anstelle von ((b 2 c, t), (b 2 c + 1, t)). Die Ki,j lassen sich wie folgt iterativ bestimmen. Fur¨ i = bm/2c + 1 gilt:   (j − 1, &), falls Di,j = Di−1,j−1 + d(S1(i),S2(j)) Ki,j = (j, ↓) , falls Di,j = Di−1,j + 1  Ki,j−1 , falls Di,j = Di,j−1 + 1 Treffen mehrere F¨alle zu, so kann man einen beliebigen m¨oglichen Fall w¨ahlen. Fur¨ i > bm/2c + 1 erhalten wir:   Ki−1,j−1, falls Di,j = Di−1,j−1 + d(S1(i),S2(j)) Ki,j = Ki−1,j , falls Di,j = Di−1,j + 1  Ki,j−1 , falls Di,j = Di,j−1 + 1

68 wobei auch hier unter den m¨oglichen F¨allen beliebig gew¨ahlt werden kann. Da wir zur Ermittlung der D- und K-Werte in der i-ten Zeile nur die (i − 1)-te Zeile ben¨otigen, brauchen wir zur Bestimmung von Km,n w¨ahrend des Algorithmus nur die aktu- elle und die letzte Zeile zu speichern. Der Platzbedarf zur Bestimmung der Kante uber¨ die Mittellinie ist damit O(n). Außerdem mussen¨ w¨ahrend des rekursiven Algorithmus die bereits ermittelten Teilpfade gespeichert werden, was einen Platzbedarf von O(m + n) verursacht. Bezuglich¨ der Laufzeit stellen wir fest, daß die Bestimmung trivialer Alignments sowie die Verkettung von Teil-Alignments insgesamt einen Aufwand von O(m + n) erfordern. Damit haben wir nun noch die gesamte Laufzeit fur¨ die Bestimmung der Kanten uber¨ die Mittellinie zu bestimmen. Fur¨ die Bestimmung dieser Kante bei einer Matrix von m + 1 Zeilen und n + 1 Spalten kann der Aufwand durch cmn mit einer geeigneten Konstante c abgesch¨atzt werden. Durch Induktion uber¨ m k¨onnen wir zeigen, daß der Gesamtaufwand durch 2cmn beschr¨ankt ist. Fur¨ m = 1 gilt die Behauptung offensichtlich, da nur eine solche Kante zu bestimmen ist. Sei die Behauptumg fur¨ 1 ≤ i < m bereits gezeigt. Bei der Anwendung des Algorithmus auf eine Matrix mit m + 1 Zeilen und n + 1 Spalten haben wir einen Aufwand von cmn fur¨ die Bestimmung der Kante uber¨ die Mittellinie, anschließend haben wir das Problem fur¨ 2 Matrizen mit h¨ochstens (m + 1)/2 Zeilen und n1 + 1 bzw. n2 + 1 Spalten zu l¨osen, wobei n1 + n2 ≤ n gilt. Nach Induktionsannahme ist die Zeit fur¨ die L¨osung der Teilprobleme m m beschr¨ankt durch 2c 2 n1 sowie 2c 2 n2, insgesamt durch cmn. Damit ergibt sich fur¨ die gesamte Laufzeit eine Absch¨atzung von 2cmn. 2

Beispiel 3.6 Fur¨ die Bestimmung der Kante uber¨ die Mittellinie erhalten wir in unserem Beispiel folgende Tabelle, von der jeweils die aktuelle und die vorige Zeile im Speicher sind. t r e p p e 0 1 2 3 4 5 6 t 1 0 1 2 3 4 5 e 2 1 1 1 2 3 4 m 3 2 2 2 2 3 4 p (0, ↓) 4 (1, ↓) 3 (1, &) 3 (2, &) 3 (3, &) 2 (4, &) 2 (4, &) 3 e (0, ↓) 5 (1, ↓) 4 (1, ↓) 4 (1, &) 3 (3, &) 3 (3, &) 3 (4, &) 2 l (0, ↓) 6 (1, ↓) 5 (1, ↓) 5 (1, &) 4 (1, &) 4 (3, &) 4 (4, &) 3  α p α  Die Kante uber¨ die Mittellinie ist (4, &); d.h., es ergibt sich das optimale Alignment 1 2 , β1 p β2 wobei (α1, β1) ein optimales Alignment von (tem,trep) und (α2, β2) ein optimales Alignment von (el,e) ist. Das hier besprochene Verfahren zur Linearisierung des Platzbedarfes kann auf viele andere Algorithmen der dynamischen Programmierung ubertragen¨ werden. Es sei empfohlen, zur Ubung¨ das Rucksackproblem mit linearem Platzbedarf zu l¨osen.

3.6 L¨osung in subquadratischer Zeit

In diesem Abschnitt soll ein Algorithmus zur Ermittlung des Levenshtein-Abstandes vorge- stellt werden, der eine Laufzeit von O(mn/ log(mn)) besitzt. Ein ¨ahnlicher Algorithmus wur- de fur¨ die Multiplikation Boolescher Matrizen durch Arlazarov, Dinic, Kronrod und Faradzev

69 angegeben, weshalb man dieses Verfahren oft als Four Russians algorithm in der Literatur findet. Es seien S1 und S2 W¨orter mit |S1| = m, |S2| = n. Der Einfachheit halber nehmen wir an, daß m = pm0 und n = qn0 fur¨ naturliche¨ Zahlen p, q gilt. Wir uberdecken¨ die Alignment-Tabelle mit Bl¨ocken der Gr¨oße (p + 1) × (q + 1), deren 0 0 0 0 R¨ander sich uberlappen.¨ Der Block Bi0,j0 mit 0 ≤ i ≤ m − 1, 0 ≤ j ≤ n − 1 enth¨alt die Felder (i, j) mit i0p ≤ i ≤ (i0 + 1)p, j0q ≤ j ≤ (j0 + 1)q. Das folgende Bild zeigt eine Uberdeckung¨ fur¨ m = 12, n = 20, p = 3, q = 4.

B0,0 B0,1 B0,2 B0,3 B0,4

B1,0 B1,1 B1,2 B1,3 B1,4

B2,0 B2,1 B2,2 B2,3 B2,4

B3,0 B3,1 B3,2 B3,3 B3,4

Die Idee des Algorithmus besteht darin, die Di,j-Werte nur auf den R¨andern der Bl¨ocke, 0 0 mn d.h. fur¨ i = pi und j = qj , zu berechnen. Damit w¨aren insgesamt nur O( pq ) Werte aus- zurechnen. Man nutzt dabei aus, daß der untere und der rechte Rand des Blocks Bi0,j0 0 0 vollst¨andig durch den linken und oberen Rand und die Teilw¨orter S1[pi + 1 . . . p(i + 1)] 0 0 sowie S2[qj + 1 . . . q(j + 1)] bestimmt sind. Wir gehen in zwei Phasen vor. Zuerst wird die sogenannte Blockfunktion bestimmt, d.h., fur¨ jede m¨ogliche Konstellation von oberem und linkem Rand sowie zugeh¨origen Teilw¨ortern werden der untere und der rechte Rand bestimmt. Anschließend werden die Di,j-Werte auf den R¨andern der Bl¨ocke ermittelt, wobei fur¨ einen Block der Wert der zugeh¨origen Blockfunktion aufgesucht werden muß. Da die Di,j-Werte beliebig groß werden k¨onnen, arbeiten wir nicht mit ihnen selbst, son- dern mit sogenannten Offset-Werten, das sind Differenzen von Di,j-Werten:

Definition 3.10 Fur¨ 1 ≤ i ≤ m und 1 ≤ j ≤ n seien

• Hi,j = Di,j − Di,j−1 (horizontaler Offset) und

• Vi,j = Di,j − Di−1,j (vertikaler Offset).

Der Wert Dm,n kann leicht aus den Offset-Werten berechnet werden, z.B. als: Dm,n = Pm Pn i=1 Vi,0 + j=1 Hm,j. Um den Levenshtein-Abstand zu ermittlen, brauchen wir also nur die vertikalen bzw. horizontalen Offset-Werte auf den vertikalen bzw. horizontalen R¨andern der Bl¨ocke zu berechnen.

Lemma 3.14 Hi,j ∈ {−1, 0, 1} fur¨ 0 ≤ i ≤ m, 1 ≤ j ≤ n, Vi,j ∈ {−1, 0, 1} fur¨ 1 ≤ i ≤ m, 0 ≤ j ≤ n.

70 Beweis. Wir zeigen die Behauptung fur¨ die horizontalen Offset-Werte; der Beweis fur¨ die vertikalen Werte ist analog. Wegen Di,j ≤ Di,j−1 + 1 folgt Hi,j ≤ 1. Wir mussen¨ also nur Hi,j ≥ −1 zeigen, was im folgenden durch Induktion uber¨ i geschieht. Fur¨ i = 0 gilt H0,j = D0,j − D0,j−1 = j − (j − 1) = 1. Sei nun gezeigt, daß Hi−1,j ≥ −1 fur¨ 1 ≤ j ≤ n erfullt¨ ist. Gem¨aß der Rekursionsbeziehung fur¨ die D-Werte ergeben sich 3 F¨alle:

1. Di,j = Di,j−1 + 1: Dann gilt Hi,j = 1.

2. Di,j = Di−1,j−1+d(S1(i),S2(j)): Wegen Di,j−1 ≤ Di−1,j−1+1 ≤ Di,j +1 folgt Hi,j ≥ −1.

3. Di,j = Di−1,j + 1. Nach Induktionsvoraussetzung gilt Hi−1,j ≥ −1 und damit Di,j ≥ Di−1,j−1. Außerdem gilt Di,j−1 ≤ Di−1,j−1 + 1 und damit Hi,j ≥ −1. 2 Als n¨achstes beweisen wir, daß die vertikalen bzw. horizontalen Offset-Werte am rechten bzw. unteren Rand eines Blockes eindeutig durch die vertikalen bzw. horizontalen Offset- Werte am linken bzw. oberen Rand sowie die zum Block geh¨origen Teilw¨orter bestimmt sind. (Wir zeigen sogar noch allgemeiner, daß alle Offset-Werte im Block eindeutig bestimmt sind.)

0 0 0 0 Lemma 3.15 Die Werte Hi,j, Vi,j mit i p+1 ≤ i ≤ (i +1)p, j q+1 ≤ j ≤ (j +1)q sind durch 0 0 Hi0p,j0q+1,Hi0p,j0q+2,...,Hi0p,(j0+1)q, Vi0p+1,j0q,Vi0p+2,j0q,...,V(i0+1)p,j0q und S1[i p + 1 ... (i + 0 0 1)p], S2[j q + 1 ... (j + 1)q] eindeutig bestimmt.

Beweis. Es genugt¨ zu zeigen, daß Hi,j und Vi,j eindeutig durch Vi,j−1, Hi−1,j, S1(i) und S2(j) bestimmt sind. Die Behauptung des Lemmas folgt dann per Induktion. Es gilt

Di,j = min{Di−1,j−1 + d(S1(i),S2(j)),Di−1,j + 1,Di,j−1 + 1}

= min{Di,j−1 − Vi,j−1 + d(S1(i),S2(j)),Di,j−1 − Vi,j−1 + Hi−1,j + 1,Di,j−1 + 1}

= Di,j−1 + min{d(S1(i),S2(j)) − Vi,j−1,Hi−1,j − Vi,j−1 + 1, 1}

und damit Hi,j = min{d(S1(i),S2(j)) − Vi,j−1,Hi−1,j − Vi,j−1 + 1, 1}. Analog erh¨alt man

Vi,j = min{d(S1(i),S2(j)) − Hi−1,j,Vi,j−1 − Hi−1,j + 1, 1}.

2 Damit gibt es eine Blockfunktion

f : {−1, 0, 1}p × {−1, 0, 1}q × Σp × Σq → {−1, 0, 1}p × {−1, 0, 1}q,

wobei f(V~1, H~ 1, α, β) = (V~2, H~ 2) bedeutet, daß der Block mit dem linken Rand V~1, dem oberen Rand H~ 1, und den Teilw¨ortern α von S1 und β von S2 den rechten Rand V~2 und den unteren Rand H~ 2 besitzt. Fur¨ eine Eingabe (V~1, H~ 1, α, β) kann der Wert der Blockfunktion durch dynamische Programmierung mit einem Aufwand von O(pq) bestimmt werden. Der gesamte Algorithmus ergibt sich wie folgt:

1. Bestimme die Blockfunktion fur¨ alle m¨oglichen Eingaben.

71 2. Berechne durch dynamische Programmierung auf den horizontalen Blockr¨andern die H-Werte und auf den vertikalen Blockr¨andern die V -Werte.

(a) Setze Vi,0 = 1, H0,j = 1 fur¨ 1 ≤ i ≤ m, 1 ≤ j ≤ n. (b) Ermittle fur¨ jeden Block den rechten und unteren Rand durch Nachschlagen der Blockfunktion.

Die Laufzeit fur¨ Schritt 1 betr¨agt O((3|Σ|)p+qpq), da es (3|Σ|)p+q Argumente fur¨ die Block- funktion gibt und die Berechnung des Funktionswertes fur¨ ein Argument durch dynamische Programmierung einen Aufwand von O(pq) kostet. mn In der zweiten Phase haben wir fur¨ O( pq ) Bl¨ocke die Blockfunktion aufzusuchen. Dies mn(p+q) kostet einen Aufwand von O(p + q) pro Block, insgesamt also O( pq ). Nehmen wir der Einfachheit halber m = n an und setzen wir p = q = (log3|Σ| n)/2, so erhalten wir einen Aufwand von O(n log2 n) fur¨ die Berechnung der Blockfunktion und von O(n2/ log n) fur¨ die Bestimmung des Levenshtein-Abstandes. Zusammenfassend k¨onnen wir feststellen:

Satz 3.16 Fur¨ S1,S2 mit |S1| = |S2| = n kann der Levenshtein-Abstand mit einem Aufwand von O(n2/ log n) bestimmt werden.

Das hier gezeigte Resultat ist eher von theoretischem Wert. Fur¨ praktische Anwendungen l¨aßt sich die Idee nutzen, indem man p = 1 und q so w¨ahlt, daß ein Wort der L¨ange q sowie ein Vektor der Dimension q uber¨ {−1, 0, 1} in einem Wort des Computers (z.B. 32 Bit) gespeichert werden kann. Dies erm¨oglicht eine Beschleunigung um den Faktor q.

3.7 Multiple Alignments

Wir wollen zuletzt das Problem des Alignments von mehr als zwei Sequenzen betrachten. Dieses ist seit einigen Jahren ein heißes Forschungsthema, da es einerseits entscheidende Be- deutung in der Molekularbiologie besitzt (insbesondere bei der Strukturvorhersage von Ei- weißmolekulen)¨ und andererseits nicht so einfach wie das Problem des paarweisen Alignments gel¨ost werden kann.

Motivation. Proteine aus einer gemeinsamen Familie besitzen ¨ahnliche biochemische Ei- genschaften und eine ¨ahnliche dreidimensionale Struktur; sie k¨onnen jedoch als Aminos¨aure- Sequenzen sehr unterschiedlich aussehen. Ein typisches Beispiel ist das H¨amoglobin, das in Insekten wie in S¨augetieren ¨ahnliche Struktur und Eigenschaften aufweist, wobei entwick- lungsbiologisch weit entfernte Arten sehr verschiedene Aminos¨aure-Sequenzen besitzen. Man nimmt an, daß die ¨ahnlichen biochemischen Eigenschaften durch lokale Sequenz-Ahnlichkeiten¨ bedingt sind. Paarweise lokale Alignments sind hier von geringem Nutzen, da bei zu großer globaler Ahnlichkeit¨ nicht die wesentlichen Ahnlichkeiten¨ entdeckt werden und bei zu großer Unterschiedlichkeit sich lokale Sequenz¨ahnlichkeiten zuf¨allig ergeben. Darum versucht man, die lokalen Ahnlichkeiten¨ durch ein gemeinsames Alignment mehrerer Sequenzen der Familie zu finden. Hat man fur¨ eine Familie ein (hoffentlich korrektes) multiples Alignment ermittelt, so kann man fur¨ eine neu erhaltene Sequenz testen, ob diese zur Familie geh¨ort, indem man sie mit dem Alignment vergleicht.

72 Bewertung multipler Alignments. Wie eine realistische Bewertung eines multiplen Ali- gnments aussehen sollte, ist nicht offensichtlich. Als praktikabel haben sich sogenannte Sum- of-pairs-Bewertungen (SP-Bewertung) erwiesen, bei denen die Bewertung eines k-Tupels als k(k−1) Summe der Bewertungen der 2 in diesem k-Tupel enthaltenen Paare entsteht. Eine forma- le Definition geben wir fur¨ die Levenshtein-Bewertung. Analog kann man z.B. fur¨ Ahnlichkeits-¨ Bewertungen verfahren.

Definition 3.11 Es seien S1,S2,...,Sk W¨orter uber¨ Σ. Ein multiples Alignment von (S1,S2,...,Sk) 0 0 0 0 ist ein k-Tupel (S1,S2,...,Sk) von W¨ortern gleicher L¨ange uber¨ Σ∪{ }, wobei St aus St durch Einfugen¨ von entsteht. 0 0 0 0 Die Levenshtein-Bewertung eines Alignments (S1,S2,...,Sk) mit |St| = n ergibt sich als

n 0 0 0 X 0 0 0 d(S1,S2,...,Sk) = d(S1(t),S2(t),...,Sk(t)) mit t=1 X d(a1, a2, . . . , ak) = d(ai, aj) fur¨ a1, a2, . . . , ak ∈ Σ ∪ { }. 1≤i

Der Vorteil einer SP-Bewertung ist, daß sie symmetrisch ist, d.h. daß man ein k-Tupel des Alignments durch die Anzahl der Vorkommen jedes Symbols aus Σ ∪ { } (H¨aufigkeitsvektor) ersetzen kann. Die Levenshtein-Bewertung eines H¨aufigkeitsvektors (h0, h1, . . . , hr) mit r = P |Σ| ergibt sich als i

Beispiel 3.7 Fur¨ Σ = {a, b}, hat das Alignment das Profil a a b a 3 0 0 0 3 0 b a a b a 0 4 4 2 0 3 a a a a 1 0 0 2 1 1 a a a b b Die Bewertung betr¨agt 3 + 0 + 0 + 4 + 3 + 3 = 13.

Exakte L¨osung. Sind die Zeichenketten S1,S2,...,Sk der L¨angen n1, n2, . . . , nk gegeben, so k¨onnen wir das globale Alignment-Problem analog zum paarweisen Problem l¨osen, indem

wir durch dynamische Programmierung die Bewertungen Dt1,t2,...,tk der optimalen multiplen Alignments von S1[1 . . . t1], S2[1 . . . t2], ..., Sk[1 . . . tk] bestimmen. Graphentheoretisch ist dies die Suche nach dem kurzesten¨ Weg von (0, 0,..., 0) nach (n1, n2, . . . , nk) im Graphen mit Kantengewichten (V, E, d), wobei

V = {(t1, t2, . . . , tk) : 0 ≤ ti ≤ ni, 1 ≤ i ≤ k}, 0 0 0 0 0 0 0 E = {((t1, t2, . . . , tk), (t1, t2, . . . , tk)) : (t1, t2, . . . , tk) 6= (t1, t2, . . . , tk), ti ≤ ti ≤ ti + 1}

und

0 0 0 X 0 0 0 d((t1, t2, . . . , tk), (t1, t2, . . . , tk)) = di,j((t1, t2, . . . , tk), (t1, t2, . . . , tk)) mit i

73 Praktikabel ist diese Methode schon fur¨ kleine Werte von k nicht mehr, da der Aufwand O(nk) betr¨agt. Wir besch¨aftigen uns im folgenden mit zwei heuristischen Ans¨atzen. Zun¨achst geben wir eine N¨aherungsl¨osung mit einer garantierten Fehlerschranke an. Danach stellen wir ein Branch-and-Bound-Verfahren vor, bei dem man die exakte L¨osung bestimmt, jedoch dank der Verwendung von Absch¨atzungen nicht alle Knoten des Graphen betrachten muß.

N¨aherungsl¨osungen. Eine h¨aufig benutzte Heuristik zur Erzeugung einer N¨aherungsl¨osung ist das Alignment von Alignments. Zun¨achst bildet man paarweise Alignments fur¨ jeweils ¨ahnliche W¨orter; sp¨ater fugt¨ man je 2 Alignments zu einem gr¨oßeren zusammen, wobei die Teil-Alignments nicht mehr ge¨andert werden. Damit wird das Alignment von Alignments zu einem paarweisen Alignment uber¨ einem neuen Alphabet. Besonders gut eignen sich SP- Bewertungen fur¨ diesen Ansatz. Die Qualit¨at der N¨aherungsl¨osung h¨angt wesentlich von der Reihenfolge der Alignment- Operationen ab. Diese wird h¨aufig durch einen Baum festgelegt. Die B¨aume spiegeln oft entwicklungsbiologische Verwandschaften wider (phylogenetische B¨aume). Wir werden nun fur¨ einen speziellen Baum zeigen, daß ein Alignment an diesem Baum eine garantierte Gute¨ erreicht.

∗ Definition 3.12 Es seien S1,S2,...,Sk W¨orter uber¨ Σ. Es sei i ∈ {1, 2, . . . , k} so gew¨ahlt, daß   X X  D(Si∗ ,Sj) = min D(Si,Sj) 1≤i≤k j6=i∗  j6=i  gilt. Der zentrale Stern (central star) fur¨ S1,S2,...,Sk ist der Graph G = (V,E) mit V = {1, 2, . . . , k} und E = {(i∗, j): j 6= i∗}.

Das Alignment am zentralen Stern geschieht wie folgt. Man bildet zun¨achst die optimalen (j) 0 ∗ paarweisen Alignments von (Si∗ ,Sj). Diese Alignments haben die Form (Si∗ ,Sj). Es sei Si∗ (j) das kurzeste¨ Wort, das aus jedem Wort Si∗ durch Einfugen¨ von erhalten werden kann. Dann (j) 0 kann man jedes Alignment (Si∗ ,Sj) durch Einfugen¨ von Paaren ( , ) zu einem Alignment ∗ ∗ ∗ ∗ der Form (Si∗ ,Sj ) umwandeln. Wegen d( , ) = 0 hat das Alignment (Si∗ ,Sj ) die gleiche (j) 0 ∗ ∗ ∗ Bewertung wie (Si∗ ,Sj). Unser gesamtes multiples Alignment ist (S1 ,S2 ,...,Sk).

Beispiel 3.8 Wir betrachten S1 = aaba, S2 = baaba, S3 = aaaa, S4 = aaabb. Dann gilt i∗ = 1, und die optimalen paarweisen Alignments sind

a a b a a a b a a a b a . b a a b a a a a a a a b b a

∗ Wir erhalten dann S1 = aab a; das Alignment am zentralen Stern ergibt:

a a b a b a a b a a a a a a a b b a

74 Satz 3.17 Es sei d die Bewertung des Alignments von S1,S2,...,Sk am zentralen Stern. Dann gilt d ≤ 2D(S1,S2,...,Sk). ∗ ∗ ∗ ∗ Beweis. O.B.d.A. gelte i = 1. Das Alignment am zentralen Stern sei (S1 ,S2 ,...,Sk), das 0 0 0 optimale Alignment sei (S1,S2,...,Sk). ∗ ∗ ∗ P ∗ ∗ Es gilt d = d(S1 ,S2 ,...,Sk) = i

X 0 0 X X 2D(S1,S2,...,Sk) = d(Si,Sj) ≥ D(Si,Sj) ≥ k D(S1,Sj) i6=j i6=j 1

2(k−1) und damit d ≤ k D(S1,S2,...,Sk). 2

Branch-and-Bound-Verfahren. Die Bestimmung des kurzesten¨ Weges erfolgt im Prinzip nach dem Dijsktra-Algorithmus zur Suche nach dem kurzesten¨ Weg von Knoten (0,..., 0) nach Knoten (n1, n2, . . . , nk). Dabei wird allerdings ein Knoten, uber¨ den der minimale Pfad garantiert nicht fuhren¨ kann, von der Betrachtung ausgeschlossen. Dazu benutzen wir folgende untere Absch¨atzung A(v) fur¨ die L¨ange des kurzesten¨ Weges von v = (v1, v2, . . . , vk) nach (n1, n2, . . . , nk): X A(v) = Ai,j(vi, vj) mit 1≤i

Ai,j(vi, vj) := D(Si[vi + 1 . . . ni],Sj[vj + 1 . . . nj]) X r r = D(Si [1 . . . ni − vi],Sj [1 . . . nj − vj]). 1≤i

Fur¨ ein Paar (i, j) k¨onnen alle Werte Ai,j(vi, vj), 0 ≤ vi ≤ ni, 0 ≤ vj ≤ nj, durch dynamische Programmierung mit einem Aufwand von O(ninj) berechnet werden. Dies geschieht in einem Pr¨aprozessing. Fur¨ einen Knoten v kann dann A(v) durch Aufsuchen der Werte Ai,j(vi, vj) mit einem Aufwand von O(k2) bestimmt werden. Ist D(v) die L¨ange des kurzesten¨ Wegen von (0, 0,..., 0) nach v, so kann der kurzeste¨ Weg von (0, 0,..., 0) nach (n1, n2, . . . , nk) nicht uber¨ v fuhren,¨ wenn D(v) + A(v) > M gilt, wobei M eine obere Schranke fur¨ die L¨ange des kurzesten¨ Wegen von (0, 0,..., 0) nach (n1, n2, . . . , nk) ist. Eine solche Schranke wird ublicherweise¨ durch eine N¨aherungsl¨osung er- mittelt (z.B. Alignment am zentralen Stern). Im Algorithmus speichern wir fur¨ jeden bereits erreichten Knoten v den Wert d(v) des aktuell besten Pfades nach v sowie einen Pointer P (v) auf den Vorg¨anger von v auf diesem Pfad. Die erreichten Knoten sind aufgeteilt in eine Menge S von Knoten, fur¨ die bereits ein optimaler Pfad gefunden wurde, und in die Menge Q der restlichen erreichten Knoten. Dabei sind die Knoten in Q nach dem aktuellen d-Wert geordnet, und der jeweils erste Knoten in Q kann entfernt werden. Ein Knoten w wird nur dann neu in Q aufgenommen, wenn d(w) + A(w) ≤ M gilt.

75 Satz 3.18 Der Branch-and-Bound-Algorithmus findet das optimale Alignment mit einem P 2 Aufwand von O( 1≤i

Algorithmus 3.5 Dijkstra-Algorithmus mit Schranken Eingabe: Graph G = (V, E, d) mit nichtnegativen Kantengewichten d, Startknoten s, Zielknoten t, obere Schranke M fur¨ L¨ange des kurzesten¨ Weges von s nach t Funktion A : V → IR+, wobei A(w) untere Schranke fur¨ L¨ange des kurzesten¨ Weges von w nach t ist Ausgabe: kurzester¨ Weg von s nach t (1) Q ← s; S ← ∅; d(s) ← 0; (2) while Q 6= ∅ (3) v ← erster Knoten in Q; (4) Verschiebe v von Q nach S; (5) foreach Nachfolger w von v (6) if d(v) + d(v, w) + A(w) ≤ M and d(v) + d(v, w) ≤ d(w) then (7) d(w) ← d(v) + d(v, w); P (w) ← v; (8) Sortiere w in Q neu ein.

Weitere Methoden. Zahlreiche andere Verfahren zur Ermittlung von N¨aherungsl¨osungen wurden vorgeschlagen und ausfuhrlich¨ getestet. Wir erw¨ahnen kurz 2 M¨oglichkeiten:

• Motif-Suche: Es wird eine Teil-Sequenz (motif, anchor, block) gesucht, die in allen W¨ortern ungef¨ahr vokommt. Diese Stellen werden aligniert. Dadurch wird jedes Wort in zwei Teile zerlegt. In diesen Teilen sucht man erneut nach Motiven.

• Hidden Markov Modelle: Es wird zun¨achst ein Profil als Startalignment bestimmt. Mit diesem Profil werden alle Sequenzen aligniert. Es entsteht ein neues Profil. Dieser Prozeß wird fortgesetzt, bis sich das Profil nicht mehr ¨andert.

76 Kapitel 4

Indexieren von Texten

4.1 Einfuhrung¨

Wir gehen jetzt von folgender Problemstellung aus. Gegeben ist ein sehr langer und un- ver¨anderlicher Text T der L¨ange n. Ziel ist es, den Text so aufzuarbeiten, daß bei der Suche nach einem Wort P (oder nach einem allgemeineren Suchmuster) nicht der ganze Text durch- sucht werden muß. Diese Aufgabenstellung ergibt sich z.B. bei der Suche im Internet oder in Genom-Datenbanken. In gewisser Weise ist diese Aufarbeitung vergleichbar mit einem Index in einem Buch, der fur¨ wichtige Stichw¨orter Verweise auf die zugeh¨origen Seiten des Buches gibt. Die wohl bekannteste Art, einen Text T zu indexieren, stellt der Suffixbaum dar. Dieser ist eine kompakte Version des Suchwortbaumes aller Suffixe von T . Ob ein Wort P in T vor- kommt, l¨aßt sich feststellen, indem man nach einem mit P beschrifteten Pfad im Suffixbaum von T sucht. Der Aufwand dafur¨ betr¨agt O(|P |), wenn man die Alphabetgr¨oße als Konstante betrachtet. Bezuglich¨ des Einflusses der Alphabetgr¨oße gelten die zu Suchwortb¨aumen ge- machten Aussagen aus Kapitel 2.1, Seite 43. Eine weitere M¨oglichkeit der Indexierung stellen Suffix-Arrays dar. Das Suffix-Array von T gibt die Reihenfolge der Suffixe von T in lexikogra- fischer Ordnung an. Die Suche nach einem Wort P kann durch bin¨are Suche im Suffix-Array von T erfolgen. Der Aufwand dafur¨ betr¨agt O(|P | · log |T |) und ist unabh¨angig von der Alpha- betgr¨oße. (Es existieren schnellere Algorithmen fur¨ die Suche, die aber zus¨atzliche Strukturen ben¨otigen.) Vorteile des Suffix-Arrays gegenuber¨ dem Suffixbaum sind seine Einfachheit und der geringere Platzbedarf.

4.2 Datenstrukturen fur¨ Indexe

Im folgenden sei S ein Wort der L¨ange n uber¨ dem Alphabet Σ der M¨achtigkeit σ. Außerdem sei # ∈/ Σ ein Sondersymbol (Textende). Mit Si, 1 ≤ i ≤ n + 1, bezeichnen wir das Suffix S[i . . . n].

4.2.1 Suffixb¨aume Die Grundidee ist, den Suchwort-Baum fur¨ die Menge der Suffixe des Textes S# zu konstru- ieren. Durch das Sondersymbol ist gew¨ahrleistet, daß es fur¨ jedes Suffix α von S ein Blatt mit der Pfad-Beschriftung α# gibt. Das Blatt fur¨ das i-te Suffix ist mit i beschriftet.

77 Definition 4.1 Es sei S ∈ Σ∗ ein Wort mit |S| = n und # ∈/ Σ ein Sonderzeichen. Der Suffix-Suchwortbaum (suffix trie) von S ist Trie(S1#,S2#,...,Sn#, #). Der Suchwort-Baum wird jedoch nicht selbst benutzt, da er eine quadratische Anzahl von Knoten besitzt. Verantwortlich dafur¨ sind innere Knoten mit dem Ausgangsgrad 1. Deshalb wird der Suchwort-Baum modifiziert — es entsteht der Suffixbaum.

Definition 4.2 Es sei S ∈ Σ∗ ein Wort und # ∈/ Σ ein Sonderzeichen. Der Suffixbaum (suffix tree) T (S) von S entsteht, indem man im Suffix-Trie von S jeden maximalen Weg, dessen innere Knoten einen Ausgangsgrad von 1 besitzen, durch eine Kante mit der gleichen Beschriftung ersetzt.

Lemma 4.1 Die Zahl der Knoten von T (S) ist h¨ochstens 2n mit n = |S|.

Beweis. Wir konstruieren T (S), indem wir die Suffixe S1#,S2#,...,Sn#, # nacheinander einfugen.¨ Das Einfugen¨ des i-ten Suffixes erfolgt, indem man einen Pfad mit der Beschriftung S[i . . . n] sucht. Gibt es einen Pfad der Beschriftung S[i . . . t − 1], jedoch keinen mit S[i . . . t], so wird am Ende des Pfades S[i . . . t − 1] eine neue Kante mit der Beschriftung S[t . . . n]# eingefugt.¨ Eventuell wird dabei eine bestehende Kante in zwei Kanten geteilt. Damit entstehen fur¨ jedes Suffix ein neues Blatt und h¨ochstens ein neuer innerer Knoten. 2 Um nicht nur die Knotenzahl, sondern auch die Gesamtgr¨oße des Suffixbaumes linear zu beschr¨anken, mussen¨ wir die Kantenbeschriftungen komprimieren. Da die Beschriftung jeder Kante ein Infix von S ist, ersetzen wir eine Beschriftung α durch ein Paar [i, j] mit S[i . . . j] = α.

Beispiel 4.1 Der Suffixbaum fur¨ S = abaabaaabaaa sieht wie folgt aus:

# 13 a a b b a b a # a b a a a a a b a a 12 a b # a a a a a a # # a # # a b b 1 # a 11 9 8 a 2 b 10 b a a a a a a a # a a b a 7 # # # a a 5 4 6 a # 3

Mit komprimierter Beschriftung ergibt sich folgendes Aussehen (statt [i, i] schreiben wir [i]):

78 [13] 13

[1] [2,4] [2,4] [13]

[5,13] [3] 12 [8] [5,13] [8] [13] [13] [13] [8] 1 11 9 8 [5,8] 2 10[13]

[13] [9,13] [9,13] [9,13] 7 [9,13] 5 4 6

3

4.2.2 Suffix-Arrays Eine Alternative zu Suffixb¨aumen stellen Suffix-Arrays dar. Sie sind einfach zu implemen- tieren, unabh¨angig von der Alphabetgr¨oße und ben¨otigen ublicherweise¨ ca. ein Viertel des Platzes eines Suffixbaumes.

Definition 4.3 Es sei S ∈ Σ∗ mit |S| = n. Das Suffix-Array von S ist das (n + 1)- dimensionale Feld AS mit AS[i] = j genau dann, wenn Sj das lexikografisch i-te Suffix von S ist.

Insbesondere gilt immer AS[i] = |S| + 1, da das leere Wort das lexikografisch kleinste Suffix ist.

Beispiel 4.2 Fur¨ S = abaabaaabaaa gilt AS = (13, 12, 11, 10, 6, 7, 3, 8, 4, 1, 9, 5, 2). Fur¨ S = mississippi gilt AS = (12, 11, 8, 5, 2, 1, 10, 9, 7, 4, 6, 3).

4.2.3 Varianten und Erweiterungen Implizite Suffixb¨aume Der implizite Suffixbaum von S entsteht, indem man im Such- wortbaum Trie(S1,S2,...,Sn) die Wege kontrahiert. Fur¨ jedes Suffix von S gibt es einen Pfad; wegen des fehlenden Endsymbols gibt es aber nicht fur¨ jedes Suffix ein Blatt. Von Nutzen sind implizite Suffixb¨aume, wenn der Text online verarbeitet werden soll (z.B. beim Lempel-Ziv-Algorithmus).

Beispiel 4.3 Der implizite Suffixbaum von S = abaabaaabaaa sieht wie folgt aus:

79 a a b b a b a a b a a a a a b a a a b # a a a a a a a # a b b 1 a a 2 b b a a a a a a a a a a b # # # a a 5 4 6 a # 3

Indexe mehrerer Texte. Gelegentlich ist ein Index mehrerer Texte gewunscht,¨ z.B. wenn ganze Verzeichnisse indexiert werden sollen oder wenn nach Gemeinsamkeiten in mehre- ren Texten gesucht werden soll. Eine m¨ogliche Datenstruktur sind verallgemeinerte Suf- fixb¨aume. Fur¨ ein k-Tupel von W¨ortern (S1,...,Sk) l¨aßt sich der gemeinsame Suffixbaum T (S1,...,Sk) definieren. Die Beschriftungen der Wege zu den Bl¨attern sind dabei die Suffixe von S1#,...,Sk#. Das Blatt fur¨ das Suffix Sh[i . . . |Sh|] erh¨alt die Beschriftung (h, i). Tritt ein Suffix in mehreren W¨ortern auf, so erh¨alt das zugeh¨orige Blatt also mehrere Beschriftun- gen. Ebenso kann man gemeinsame Suffix-Arrays definieren.

Partielle Indexe. Gesucht ist ein Index, der nicht alle Suffixe eines Textes S enth¨alt, sondern nur die Suffixe Si mit i ∈ I fur¨ eine Menge I ⊆ {1, . . . , n}. Zum Beispiel wird man sich bei Texten in naturlichen¨ Sprachen nur fur¨ solche Suffixe interessieren, die an einem Wortanfang beginnen. Die Platzersparnis ist gewaltig, da nur ein Bruchteil des Textes zu indexieren ist. Zum Beispiel enth¨alt Mark Twains Tom Sawyer 387922 Zeichen, aber nur 71457 W¨orter (Index-Stellen) [11]. Datenstrukturen sind der partielle Suffixbaum sowie das partielle Suffix-Array.

Beispiel 4.4 Wir betrachten den folgenden Satz. Die Anf¨ange von W¨ortern (Index-Stellen) sind markiert.

brautkleid bleibt brautkleid und blaukraut bleibt blaukraut 1 12 18 29 33 43 49

Die W¨orter in lexikografischer Reihenfolge sind: blaukraut, bleibt, brautkleid, und Es ergibt sich folgendes partielles Suffix-Array: (49, 33, 43, 12, 1, 18, 29).

4.3 Konstruktion von Suffixb¨aumen Technische Definitionen Wir beginnen mit einigen technischen Definitionen fur¨ Suffixb¨aume bzw. allgemeiner fur¨ B¨aume, deren Kanten mit W¨ortern beschriftet sind. • Eine Position im Suffixbaum ist entweder ein Knoten oder ein Paar (e, i), wobei e = (v, α, w) eine Kante ist und i eine Zahl mit 1 ≤ i < |α| ist. Im zweiten Fall sagen wir, daß sich die Position im Inneren der Kante e befindet.

80 • Der graphentheoretische Begriff Pfad wird erweitert, indem man als Anfangs- bzw. Endpunkt auch Positionen zul¨aßt, w¨ahrend die inneren Punkte nur Knoten sind. Die Beschriftung eines Pfades erh¨alt man durch Konkatenation der Beschriftungen der Kan- ten, wobei Kanten von der Anfangs- bzw. Endposition nur teilweise eingehen. Formal definieren wir:

1. Es sei e = (v, α, w) eine Kante mit |α| = m. Dann sind (e, i) → (e, j) mit 1 ≤ i < j < m bzw. (e, i) → w mit 1 ≤ i < m bzw. v → (e, i) mit 1 ≤ i < m bzw. v → w Pfade der L¨ange 1 mit den Beschriftungen α[i + 1 . . . j] bzw. α[i + 1 . . . m] bzw. α[1 . . . i] bzw. α.

2. Sind p0 → v1 → v2 → ... → vk und vk → pk+1 Pfade der L¨ange k bzw. 1 mit den Beschriftungen α bzw. β (wobei v1, . . . , vk Knoten sind), so ist p0 → v1 → v2 → ... → vk → pk+1 ein Pfad der L¨ange k + 1 mit der Beschriftung αβ. • Offensichtlich ist ein Pfad eindeutig durch seine Startposition p und seine Beschriftung β bestimmt. Notation: Pfad β von Position p.

• Eine Position wird durch die Beschriftung β des Pfades von der Wurzel identifiziert. Notation: Position β.

• Ist p eine Position mit der Beschriftung β ∈ Σ∗ und existiert eine Position q mit der Beschriftung βx mit x ∈ Σ, so sagen wir daß von p eine Fortsetzung mit x existiert; Notation q = Next(p, x).

• Fur¨ eine Position p bezeichnen wir die L¨ange des Pfades von der Wurzel nach p als Tiefe von p, Notation depth(p), und die L¨ange der Beschriftung L(p) als String-Tiefe von p.

4.3.1 Naiver Algorithmus Analog zur Konstruktion des Suchwort-Baumes ergibt sich folgender naiver Algorithmus zur Konstruktion von Suffixb¨aumen, der bereits im Beweis von Lemma 4.1 beschrieben wurde. Dabei gibt p die aktuelle Position im Suffixbaum an.

Algorithmus 4.1 Konstruktion des Suffixbaumes (Naiver Algorithmus) Eingabe: Wort S mit |S| = n Ausgabe: Suffixbaum von S (1) T ← ({root}, ∅); (2) for i ← 1 to n + 1 (3) t ← i; p ← root; x ← S[t]; (4) while (von p gibt es eine Fortsetzung mit x) (5) p ← Next(p, x); t ← t + 1; x ← S[t]; (6) Fuge¨ bei p eine neue Kante mit der Beschriftung S[t . . . n+1] zu einem neuen Blatt mit der Beschriftung i ein. (7) return T

Das Einfugen¨ der neuen Kante in Algorithmus 4.1 geschieht folgendermaßen.

81 Ist p ein Knoten v, so werden ein neues Blatt b und die Kante (v, S[t . . . n+1], b) eingefugt.¨ Die komprimierte Kantenbeschriftung lautet [t, n + 1]. Liegt dagegen p im Inneren einer Kante, d.h. p = (e, j) mit e = (v, α, w), so wird ein neuer Knoten u zwischen v und w eingefugt¨ und e durch (v, α[1 . . . j], u) und (u, α[j + 1 ... |α|], v) ersetzt. Außerdem werden das neue Blatt b und die Kante (u, S[t . . . n + 1], b) eingefugt.¨ Benutzt man die komprimierte Beschriftung, so hat die ersetzte Kante e die Gestalt (v, [l, r], w), und die neuen Kanten sind (v, [l, l + j − 1], u), (u, [l + j, r], w) sowie (u, [t, n + 1], b). 2 Die Laufzeit des naiven Algorithmus ist O(n ), da das Einfugen¨ des Suffixes Si# im schlechtesten Fall O(n − i) Schritte kostet. Die mittlere Laufzeit ist in der Gr¨oßenordnung Θ(n log n).

4.3.2 Algorithmus von McCreight

Wie beim naiven Algorithmus werden der Reihe nach die Suffixe S1#,S2#,...,Sn#, # ein- gefugt.¨ Die Laufzeit wird verkurzt,¨ indem einige Vergleiche eingespart werden. Im folgenden sei Ti(S) der Baum nach dem Einfugen¨ von S1#,S2#,...,Si#. T0(S) besteht nur aus der Wurzel. Mit ti(S) bezeichnen wir die Stelle in S, fur¨ die beim Einfugen¨ von Si# keine Fort- setzung im Baum Ti−1(S) gefunden wird. Entscheidend fur¨ den Algorithmus von McCreight ist das folgende Lemma.

Lemma 4.2 Es sei S ein Wort der L¨ange n. Gibt es fur¨ 1 ≤ i ≤ n + 1 in Ti−1(S) einen Pfad xα, so gibt es in Ti(S) einen Pfad α.

Beweis. Ein Pfad xα ist genau dann in Ti−1(S), wenn S[j . . . j + |α|] = xα fur¨ ein j ≤ i − 1 gilt. Dann gilt aber S[j + 1 . . . j + |α|] = α, und damit ist der Pfad α in Ti(S). 2 Aus dem Lemma ergeben sich einige wichtige Folgerungen.

Folgerung 4.3 Es sei S ein Wort der L¨ange n.

1. Gibt es in Ti−1(S) einen Knoten xα, so gibt es in Ti(S) einen Knoten α.

2. Es gilt ti−1(S) ≤ ti(S) fur¨ alle 1 ≤ i ≤ n + 1. Der Algorithmus von McCreight benutzt zwei Techniken, die im folgenden vorgestellt werden.

Skip/Count-Trick Wenn im Voraus bekannt ist, daß der Pfad β im Baum enthalten ist, so braucht man bei der Suche nach der Endposition von β nicht fur¨ jede Position, sondern nur fur¨ die Knoten auf dem Pfad nach der Fortsetzung zu suchen. Befindet man sich an einem Knoten v und in β an der Stelle t, so bestimmt man die eindeutige Kante (v, α, w) mit α[1] = β[t], l¨aßt die restlichen Vergleiche entlang der Kante aus (skip) und setzt im Knoten w und an der Stelle β[t + |α|](count) fort. Genauer formulieren wir die Skip/Count-Suche wie folgt.

82 Skip/Count-Suche Eingabe: Suffixbaum T (im Aufbau), Knoten v, β ∈ Σ∗, |β| = m, Pfad von v mit Beschriftung β existiert Ausgabe: Endposition des Pfades β ab v Skip-Count-Search(T , v, β) (1) t ← 1; u ← v; (2) while t ≤ m (3) Bestimme Kante e = (u, α, w) mit α[1] = β[t]; (4) if t + |α| = m + 1 then return w; (5) if t + |α| > m + 1 then return (e, m − t + 1); (6) if t + |α| ≤ m then u ← w; t ← t + |α|;

Ist also vor der Suche bekannt, daß der Pfad β existiert, so kann durch den Skip/Count- Trick das Ende des Pfades β in einer Zeit gefunden werden, die linear in depth(β) ist (statt linear in |β|). Zum Beispiel l¨aßt sich die Endposition des Pfades baabaaaba im Suffixbaum aus Beispiel 4.1 in 2 Schritten finden. Fur¨ die Konstruktion des Suffixbaumes ist von Bedeutung, daß vor dem Einfugen¨ von Si# das Wort S[i . . . ti−1 − 1] in Ti−1 enthalten ist, also die Skip/Count-Suche anwendbar ist.

Suffix-Links

Definition 4.4 Es sei v ein Knoten in T (S) bzw. in Ti(S) mit der Pfad-Beschriftung xα, x ∈ Σ, α ∈ Σ∗. Gibt es einen Knoten w mit der Pfad-Beschriftung α, so nennen wir w das Suffix-Link von v, Bezeichnung s[v]. Suffix-Links k¨onnen genutzt werden, um die Suche abzukurzen,¨ wenn man von einer Po- sition xαγ mit x ∈ Σ nach der Position αγ sucht. Gibt es n¨amlich einen Knoten v mit der Pfadbeschriftung xα, der ein Suffix-Link (mit Beschriftung α)besitzt, so kann man einfach von s[v] aus den Pfad mit der Beschriftung γ suchen. Diese Situation tritt beim Aufbau des Suffixbaumes auf. α x α γ s[v] γ v

Lemma 4.4 Entsteht beim Einfugen¨ von Si−1# ein neuer innerer Knoten u, so besitzt u nach dem Einfugen¨ von Si# ein Suffix-Link. Beweis. Der Knoten u hat eine Pfadbeschriftung xβ. Nach Folgerung 4.3 existiert nach dem Einfugen¨ von Si# ein Knoten mit der Pfadbeschriftung β, d.h. das Suffix-Link von u. Man beachte, daß dieser Knoten beim Einfugen¨ von Si# erreicht wird bzw. entsteht. Damit kostet das Setzen des Suffix-Links von u nur konstanten Aufwand. 2 Wir k¨onnen nun die (i + 1)-te Phase des Algorithmus von McCreight formulieren:

83 1. Gilt ti = i, so bestimme ti+1 durch zeichenweisen Vergleich ab der Wurzel und der Position i + 1 in S.

2. Anderenfalls sei S[i . . . ti − 1] = xiβi; ui sei der Knoten mit der Pfad-Beschriftung xiβi; vi sei der letzte Knoten auf dem Pfad nach ui, der schon in Ti−1 vorhanden war; die Pfad-Beschriftung von vi sei xiαi; die Beschriftung der Kante von vi nach ui sei γi.

Insbesondere besitzt vi ein Suffix-Link in Ti(S); und es gilt ui 6= vi genau dann, wenn ui neu entstanden ist. Wir k¨onnen nun das Ende des Pfades S[i + 1 . . . ti − 1] = βi (gleichzeitig das Suffix-Link von ui) wie folgt finden.

0 0 (a) Ist vi die Wurzel, so gilt βi = γi = S[i]γi. Suche von der Wurzel nach γi mittels Skip/Count-Suche.

(b) Ist vi nicht die Wurzel, so suche von s[vi] aus den Pfad γi mittels Skip/Count-Suche.

Wir bestimmen dann ti+1 durch zeichenweisen Vergleich ab der Position βi im Baum und der Stelle ti in S.

Beispiel 4.5 Wir betrachten die 8. Phase der Konstruktion des Suffixbaumes von abaabaaabaaa. In der 7. Phase wurde die neue Kante an dem neuen Knoten aabaaa eingefugt.¨ Der letzte Knoten in T6 auf dem Pfad aabaaa war aa. Man folgt zun¨achst dem Suffix-Link zum Knoten a (1) und sucht von dort mittels Skip/Count-Trick den Pfad baaa (2–3). Da der Pfad im Inneren einer Kante endet, wird hier eine neue Kante mit der Beschriftung # eingefugt¨ (4) und das Suffix-Link des in Phase 7 eingefugten¨ Knoten gesetzt (5). a a b b a b a a b a a a a a b a a 1 a b # a a 3 2 a a a a a # a b b 1 # a 4 a 2 b b a a a a a a a # a a b a 7 # # # a a 5 4 6 a 5 # 3

84 Algorithmus 4.2 Konstruktion des Suffixbaumes (McCreight) Eingabe: Wort S mit |S| = n Ausgabe: Suffixbaum von S (1) T ← ({root}, ∅); v ← root; u ← root; (2) for i ← 1 to n + 1 (3) if u = v then γ ← ε; (4) else γ ← Beschriftung der Kante von v nach u; (5) if u = root then t ← i; (6) else if v = root then γ ← γ ohne erstes Zeichen; (7) else v ← s[v]; (8) p ← Skip-Count-Search(T , v, γ); q ← p; (9) while (von q gibt es eine Fortsetzung mit S[t]) (10) q ← Next(q, S[t]); t ← t + 1; (11) v ← letzter Knoten auf dem Pfad nach q; (12) Fuge¨ bei q eine neue Kante mit der Beschriftung S[t . . . n+1] zu einem neuen Blatt mit der Beschriftung i ein; (13) if u 6= root then s[u] ← p; (14) u ← q;

Zum Beweis der Linearit¨at der Laufzeit des Algorithmus von McCreight zeigen wir zun¨achst folgendes Lemma. Dabei ist vi wie oben definiert, und depthi(v) ist die Tiefe eines Knoten v in Ti(S).

Lemma 4.5 Ist vi nicht die Wurzel, so gilt depthi(s[vi]) ≥ depthi(vi) − 1.

Beweis. Alle von der Wurzel verschiedenen Knoten auf dem Weg nach vi waren schon in Ti−1(S) vorhanden und besitzen damit (paarweise verschiedene) Suffix-Links, die sich auf dem Weg nach s[vi] befinden. Da h¨ochstens einer der Knoten die Wurzel als Suffix-Link besitzt, folgt das Lemma. 2

Satz 4.6 Der Algorithmus von McCreight ermittelt den Suffix-Baum von S mit einer Laufzeit von O(n). Beweis. Die Korrektheit folgt aus der Korrektheit der Verwendung von Suffix-Links und des Skip/Count-Tricks. Fur¨ die Laufzeitabsch¨atzung betrachten wir getrennt den Aufwand w¨ahrend der Skip/Count-Suche bzw. w¨ahrend der Suche durch zeichenweise Vergleiche. Die Skip/Count-Suche beim Einfugen¨ von Si#(i-te Phase) beginnt in einer Tiefe von mindestens depthi−1(vi−1) − 1 und endet in einer Tiefe von h¨ochstens depthi−1(vi). We- gen depthi−1(vi) = depthi(vi) ergeben sich fur¨ die i-te Phase somit h¨ochstens depthi(vi) − depthi−1(vi−1) + 1 Skip/Count-Schritte. Insgesamt ist die Zahl der Skip/Count-Schritte be- schr¨ankt durch

n+1 X [depthi(vi) − depthi−1(vi−1) + 1] = depthn+1(vn+1) − depth1(v1) + n = n. i=2

85 Die zeichenweisen Vergleiche beginnen in der Phase (i + 1) an der Position ti und enden an der Position ti+1. Die Zahl der Schritte bei den zeichenweisen Vergleichen betr¨agt damit in der (i + 1)-ten Phase ti+1 − ti + 1. Insgesamt ergibt sich fur¨ die Zahl der expliziten Vergleiche eine Absch¨atzung von n X (ti+1 − ti + 1) = 2n + 2. i=0 2

4.3.3 Online-Algorithmus von Ukkonen Ukkonen gab einen Algorithmus zur Konstruktion des impliziten Suffixbaumes an, die online erfolgt. Wir beschreiben diesen Algorithmus hier als eine Variante des McCreight-Algorithmus. Beim Algorithmus von McCreight wird in der i-ten Phase (Einfugen¨ von Si#) in den bisher konstruierten Baum Ti−1(S) eine Kante mit der komprimierten Beschriftung [ti, n] eingefugt,¨ wobei S[i . . . ti − 1] das l¨angste Pr¨afix von Si ist, fur¨ das in Ti−1(S) ein Pfad vorkommt. Wir modifizieren den Algorithmus derart, daß wir statt der Beschriftung [ti, n] die Beschriftung [ti, e] benutzen, wobei e eine Variable ist, die zu unterschiedlichen Zeitpunkten verschieden interpretiert wird.

Lemma 4.7 Gilt i < ti, so ist der modifizierte Baum Ti−1(S) der implizite Suffixbaum fur¨ das Wort S[1 . . . ti−1], wobei e durch ti−1 interpretiert wird. Durch den Ukkonen-Algorithmus kann man den Suffixbaum von S bestimmen, indem man den impliziten Suffixbaum von S# bestimmt. Auf dem Wege dorthin werden die impliziten Suffixb¨aume fur¨ alle Pr¨afixe S[1 . . . ti−1] mit i < ti ermittelt.

4.4 Konstruktion von Suffix-Arrays

Das Suffix-Array kann sehr einfach aus dem Suffixbaum konstruiert werden.

Satz 4.8 AS kann aus T (S) mit einem Aufwand von O(|S|) ermittelt werden. Beweis. In jedem inneren Knoten werden die ausgehenden Kanten entsprechend ihrer Be- schriftung und damit nach dem ersten Buchstaben ihrer Beschriftung geordnet. Dann ergibt sich AS aus der Beschriftung der Bl¨atter von T (S) in DFS-Ordnung. Der Aufwand fur¨ die Sortierung ist O(|S| · log |Σ|), der Aufwand fur¨ die DFS O(|S|). 2 Die Konstruktion des Suffix-Arrays aus dem Suffix-Baum kann sinnvoll sein, wenn genugend¨ Platz zur Verfugung¨ steht, um den Suffix-Baum einmal zu ermitteln, aber nicht genug, um ihn dauerhaft zu speichern. Im folgenden geben wir platzsparende Konstruktionen an. Die erste stammt von Manber und Myers aus dem Jahr 1992, die zweite von K¨arkk¨ainen und Sanders aus dem Jahr 2003. Beide Konstruktionen benutzen die naturliche¨ Ordnung von Tupeln und die Sortierung mittels Radix Sort.

k Definition 4.5 (M, <) sei eine total geordnete Menge. Die naturliche¨ Ordnung

(a1, a2, . . . , ak)

86 Eine Menge A ⊆ M k kann mit dem folgenden Algorithmus Radix Sort sortiert werden.

Algorithmus 4.3 Radix Sort Eingabe: Menge A ⊆ M k, Ordnung (M, <) Ausgabe: A sortiert nach

Gilt M = {0, 1, . . . , r}, so kann fur¨ die stabile Sortierung das Verfahren Counting Sort verwendet werden. Damit ergibt sich fur¨ die Sortierung von A mit |A| = n ein Gesamtaufwand von O(k(n + r)). Ist k eine Konstante und gilt r ≤ n (was bei den folgenden Algorithmen der Fall sein wird), so betr¨agt der Aufwand O(n). Weiterhin ben¨otigen wir fur¨ die Konstruktion des Suffix-Arrays das inverse Suffix-Array, das fur¨ eine Zahl j die Stellung des Suffixes Sj im Suffix-Array angibt.

Definition 4.6 Es sei S ∈ Σ∗ mit |S| = n. Das inverse Suffix-Array von S ist das (n + 1)- dimensionale Feld AS mit AS[j] = i genau dann, wenn AS[i] = j.

4.4.1 Konstruktion durch Verfeinerung Es sei S ∈ Σ∗ mit |S| = n. Die Idee ist, die Zahlen i ∈ {1, 2, . . . , n + 1} zun¨achst nach den Infixen der L¨ange 1, d.h. den Symbolen S[i], dann nach den Infixen der L¨ange 2, dann nach den Infixen der L¨ange 4 bzw. allgemeiner in der i-ten Phase nach den Infixen der L¨ange i 2 zu ordnen. Dann ist nach log2 n Phasen das Suffix-Array erreicht. Formal definieren wir Relationen, die verfeinert werden.

Definition 4.7 Es sei S ∈ Σ∗ mit |S| = n. Wir definieren fur¨ k ≥ 1 die folgenden (von S abh¨angigen) bin¨aren Relationen auf {1, . . . , n + 1}.

i ≡k j : ⇐⇒ S[i . . . i + k − 1] = S[j . . . j + k − 1]

i ≺k j : ⇐⇒ S[i . . . i + k − 1]

Man beachte: S[i . . . m] ist fur¨ m > n als S[i . . . n] definiert. Offensichtlich sind die Relationen ≡k Aquivalenzrelationen,¨ w¨ahrend die Relationen ≺k 0 0 0 0 transitiv und antireflexiv sind. Aus i ≡k i , j ≡k j und i ≺k j folgt i ≺k j . Damit kann ≺k als eine Ordnung auf den Aquivalenzklassen¨ von ≡k angesehen werden, wobei: I ≺k J genau dann, wenn i ≺k j fur¨ ein i ∈ I und ein j ∈ J.

Lemma 4.9 Fur¨ S ∈ Σ∗ mit |S| = n gilt:

1. i ≡k1+k2 j ⇐⇒ (i ≡k1 j) ∧ (i + k1 ≡k2 j + k1),

2. i ≡n j ⇐⇒ i = j,

3. i ≺k1+k2 j ⇐⇒ i ≺k1 j ∨ ((i ≡k1 j) ∧ (i + k1 ≺k2 j + k1)),

4. i ≺n j ⇐⇒ S[i . . . n]

87 Beweis. Wir zeigen nur (3) und (4). Die Behauptungen (1) und (2) kann man analog beweisen.

(3) Es gilt

i ≺k1+k2 j ⇐⇒ S[i . . . i + k1 + k2 − 1]

⇐⇒ (i ≺k1 j) ∨ ((i ≡k1 j) ∧ (i + k1 ≺k2 j + k1)).

(4) Gilt nach Definition. 2 ¨ Im Algorithmus werden die Aquivalenzklassen ≡2k und die Ordnungen ≺2k fur¨ alle k ≥ 0 ¨ bestimmt, bis jede Aquivalenzklasse einelementig ist. Nach sp¨atestens dlog2 ne Phasen ist die Ordnung ≺ ermittelt. Der Algorithmus fur¨ die Konstruktion durch Verfeinerung benutzt die Arrays

• A: enth¨alt nach Schritt k die Menge {1, 2, . . . , n + 1} geordnet nach ≺2k ; am Ende AS, ¨ • A: gibt nach Schritt k die Aquivalenzklassen in ≡2k an; am Ende AS, • B: zur Zwischenspeicherung.

Konstruktion des Suffix-Arrays durch Verfeinerung: Schritt 0 (1) A ← Radix Sort({1, 2, . . . , n + 1}) nach Schlussel¨ S[j]; (2) A[A[1]] ← 1; (3) for i ← 2 to n + 1 (4) if S[A[i]] = S[A[i − 1]] then A[A[i]] ← A[A[i − 1]]; (5) else A[A[i]] ← A[A[i − 1]] + 1;

Konstruktion des Suffix-Arrays durch Verfeinerung: Schritt k ≥ 1 (1) A ← Radix Sort({1, 2, . . . , n + 1}) nach Schlussel¨ (A[j], A[j + 2k−1]); (2) B[A[1]] ← 1; (3) for i ← 2 to n + 1 (4) if (A[A[i]] = A[A[i − 1]] and A[A[i] + 2k−1] = A[A[i − 1] + 2k−1]) (5) then B[A[i]] ← B[A[i − 1]]; (6) else B[A[i]] ← B[A[i − 1]] + 1; (7) A ← B;

Die Laufzeit pro Schritt betr¨agt O(n), da Radix Sort (mit 2 Durchl¨aufen) benutzt wird.

Beispiel 4.6 Fur¨ S = mississippi ergibt sich folgender Verlauf des Algorithmus. Die Tabellen geben die Arrays A und A sowie in der Zeile fur¨ A die Grenzen zwischen den

88 ¨ Aquivalenzklassen von ≡2k an.

1 2 3 4 5 6 7 8 9 10 11 12 Schritt 0: A 12 2 5 8 11 1 9 10 3 4 6 7 A 3 2 5 5 2 5 5 2 4 4 2 1 1 2 3 4 5 6 7 8 9 10 11 12 Schritt 1: A 12 11 8 2 5 1 10 9 4 7 3 6 A 5 4 9 8 4 9 8 3 7 6 2 1 1 2 3 4 5 6 7 8 9 10 11 12 Schritt 2: A 12 11 8 2 5 1 10 9 7 4 6 3 A 5 4 11 9 4 10 8 3 7 6 2 1 1 2 3 4 5 6 7 8 9 10 11 12 Schritt 3: A 12 11 8 5 2 1 10 9 7 4 6 3 A 6 5 12 10 4 11 9 3 8 7 2 1 Im Jahre 2003 wurden gleich drei Algorithmen zur platzeffizienten Konstruktion des Suffix- Arrays in Linearzeit entdeckt (darunter der im n¨achsten Abschnitt vorgestellte). Damit ist der Verfeinerungsalgorithmus eigentlich uberholt.¨ Wir haben ihn dennoch angegeben, da ¨ahnliche Ideen auch bei anderen Algorithmen, z.B. bei der Konstruktion des minimalen DEA nach Hopcroft, zu finden sind.

4.4.2 Skew Algorithmus von K¨arkk¨ainen und Sanders Dieser neue Algorithmus (2003) konstruiert das Suffix-Array in linearer Zeit mit effizientem Platzaufwand. Er besteht im wesentlichen aus 3 Schritten.

1. Konstruiere das partielle Suffix-Array (sowie das inverse partielle Suffix-Array) fur¨ die Index-Menge J = {1 ≤ j ≤ n : j mod 3 6= 1}. Dabei sortiert man die Teilw¨orter der L¨ange 3, die an den Positionen j mit j mod 3 6= 1 beginnen, erh¨alt ein neues Wort S0 der L¨ange 2n/3 uber¨ dem Alphabet {1,..., d2n/3e} und ruft rekursiv den Skew- Algorithmus fur¨ das Wort S0 auf. Der Zeitaufwand ist O(n) sowie der Aufwand fur¨ die rekursive L¨osung des Problems der Gr¨oße d2n/3e.

2. Konstruiere (mit Hilfe des partiellen Suffix-Arrays fur¨ die Index-Menge J) das partielle Suffix-Array fur¨ die Index-Menge J = {1 ≤ j ≤ n : j mod 3 = 1}. Der Zeitaufwand ist O(n).

3. Konstruiere aus den partiellen Suffix-Arrays das gesamte Suffix-Array. Dieser Schritt ist ¨ahnlich dem Mischen bei Merge Sort und ben¨otigt eine Zeit von O(n).

Die Zeit T (n) fur¨ die L¨osung des Problems der Gr¨oße n erfullt¨ die Gleichung T (n) = O(n) + T (2n/3). Damit ergibt sich eine gesamte Laufzeit von O(n). Wir betrachten nun die einzelnen Schritte im Detail.

89 Skew Algorithmus – Schritt 1 Der Einfachheit halber nehmen wir an, daß |S| = n = 3n0 gilt. Außerdem sei das Alphabet Σ = {1, 2, . . . , σ}, und wir setzen S[n + 1] = S[n + 2] = 0. Wir sortieren zun¨achst die j ∈ J nach dem Schlussel¨ S[j . . . j + 2] mittels Radix Sort. (In der Terminologie des vorigen Abschnitts konstruieren wir die Aquivalenzklassen¨ von ≡3 geordnet nach ≺3.) Entsprechend der lexikografischen Ordnung von S[j . . . j + 2] erh¨alt jedes j mit j mod 3 6= 1 einen Namen N[j] ∈ {1,..., 2n0} (die Nummer seiner Aquivalenzklasse).¨ Es gilt also N[j1] < N[j2] genau dann, wenn S[j1 . . . j1 + 2]

S0 = N[2]N[5] ...N[3n0 − 1]N[3]N[6] ...N[3n0].

Einer Position j in S mit j mod 3 6= 1 entspricht eineindeutig eine Position j0 in S0:Fur¨ j = 3i − 1 ist j0 = i; fur¨ j = 3i ist j0 = n0 + i.

Lemma 4.10 Die Stellung von j im partiellen Suffix-Array von S fur¨ die Index-Menge J ist gleich der Stellung von j0 im Suffix-Array von S0.

Beweis. Es seien j1 und j2 Zahlen mit j1, j2 6≡ 1 mod 3. Wir mussen¨ beweisen, daß S[j1 ··· n]

Skew Algorithmus – Schritt 2

Nun ist die Ordnung der Suffixe Sj mit j mod 3 = 1 zu ermitteln. Offensichtlich ergibt sich diese aus der naturlichen¨ Ordnung bezuglich¨ (S[j],Sj+1). Die Ordnung der Suffixe Sj+1 mit j mod 3 = 1 ist aus Schritt 1 bekannt und durch das partielle Suffix-Array fur¨ die Menge J gegeben. Die Sortierung der Sj mit j mod 3 = 1 nach dem Schlussel¨ Sj+1 ist damit trivial. Anschließend genugt¨ eine Sortierung mit Counting Sort nach dem Schlussel¨ S[j], um das partielle Suffix-Array von S bezuglich¨ der Menge J zu erhalten.

Skew Algorithmus – Schritt 3 Nun sind noch die partiellen Suffix-Arrays zu mischen. Wie beim Mischen im Algorithmus Merge Sort beginnen wir in den partiellen Suffix-Arrays mit dem ersten Element und vergleichen die Suffixe bezuglich¨ der lexikografischen Ordnung. Das kleinere Suffix wird in das totale Suffix-Array eingefugt;¨ im zugeh¨origen partiellen Array wird zur n¨achsten Position gegangen. W¨ahrend dieses Mischens erfolgen Vergleiche von Suffixen der Form S3i+1 mit Suffixen der Form S3j+2 oder S3j. Wir zeigen, daß jeder dieser Vergleiche mit konstantem Aufwand ausgefuhrt¨ werden kann.

90 Zum Vergleich eines Suffixes S3i+1 mit einem Suffix S3j+2 vergleicht man die Paare (S[3i+ 1],S3i+2) und (S[3j + 2],S3j+3). Dabei ergibt sich die Reihenfolge von S3i+2 und S3j+3 aus dem inversen partiellen Suffix-Array fur¨ die Index-Menge J. Zum Vergleich eines Suffixes S3i+1 mit einem Suffix S3j vergleicht man die Tripel (S[3i + 1],S[3i + 2],S3i+3) und (S[3j],S[3j + 1],S3j+2). Dabei ergibt sich die Reihenfolge von S3i+3 und S3j+2 aus dem inversen partiellen Suffix-Array fur¨ die Index-Menge J. In jedem Fall betr¨agt die Zeit fur¨ einen Vergleich O(1), insgesamt O(n).

Beispiel 4.7 Es sei S = mississsippi. Schritt 1. Wir erhalten die folgenden Tripel mit ihren Namen. 2 5 8 11 3 6 9 12 Position in S iss iss sip pi0 ssi sss ipp i00 Teilw¨orter der L¨ange 3 3 3 5 4 6 7 2 1 Namen

Das neue Wort ist S0 = 33546721. Rekursiv erhalten wir als Suffix-Array von S0: (8, 7, 1, 2, 4, 3, 5, 6) und als partielles Suffix-Array von S fur¨ die Index-Menge J: (12, 9, 2, 5, 11, 8, 3, 6). Schritt 2. Als partielles Suffix-Array von S fur¨ die Index-Menge J ergibt sich: (1, 10, 4, 7). Schritt 3. Wir erhalten folgende partielle Suufix-Arrays und zu vergleichende Paare bzw. Tripel (die Paare bzw. Tripel werden unmittelbar beim Vergleich ermittelt und nicht in einem Array gespeichert): 1 10 4 7 12 9 2 5 11 8 3 6 mi7 pp1 si8 ss2 i00 ip5 ss4 ss6 m3 p5 s4 s6 i7 i8 p1 s2

Nach dem Mischen ergibt sich das Suffix-Array von S: (12, 9, 2, 5, 1, 11, 8, 10, 4, 7, 3, 6).

Eine Implementierung des Skew Algorithmus ist in der Originalarbeit von K¨arkk¨ainen und Sanders [9] zu finden.

4.5 Anwendungen von Suffixb¨aumen und Suffix-Arrays

Die wichtigste Anwendung und Motivation von Text-Indexen ist die schnelle (exakte oder in- exakte) Suche in einem festen Text. Außerdem kann man Regelm¨aßigkeiten, wie lange Wieder- holungen, h¨aufige Teilw¨orter oder Palindrome mit Hilfe von Suffixb¨aumen entdecken. Schließ- lich findet man Anwendungen bei effizienten Kompressionsverfahren (Lempel-Ziv, Burrows- Wheeler). Wir wollen im folgenden einige der genannten Anwendungen demonstrieren.

4.5.1 Wiederholte Suche in festem Text Suche mit Suffixb¨aumen Die Suche nach einem Wort P in einem Text T basiert auf der folgenden einfachen Uberlegung:¨ P beginnt in T an der Stelle i genau dann, wenn P ein Pr¨afix von T [i . . . n] ist. Dies ist genau dann der Fall, wenn es im Suffixbaum T (T ) einen Pfad gibt, der mit P beschriftet ist und zum Blatt i fortgesetzt werden kann. Man sucht also in T (T ) den (h¨ochstens einen) mit P beschrifteten Pfad und startet von dessen Ende eine Tiefen- oder Breitensuche. Die Menge der dabei gefundenen Bl¨atter ist die Menge der Anfangspositionen von P in T . Der Aufwand betr¨agt (ohne Berucksichtigung¨ der Alphabetgr¨oße) O(|P |) fur¨ die

91 Suche nach dem Pfad P und O(k) fur¨ die Suche nach den k Vorkommen von P . Letztere Schranke gilt, da jeder innere Knoten mindestens 2 Nachfolger hat und damit die Zahl der Knoten eines Unterbaumes linear in der Zahl seiner Bl¨atter ist.

Satz 4.11 Nach einem Pr¨aprozessing mit dem Aufwand O(|T |) k¨onnen die Vorkommen eines beliebigen Wortes P in T mit einem Aufwand von O(|P | + k) gefunden werden, wobei k die Anzahl der Vorkommen von P in T ist.

Suche mit Suffix-Arrays Man kann die Vorkommen eines Wortes P in einem Text T mit |P | = m, |T | = n durch bin¨are Suche im Suffix-Array von T bestimmen. Dabei ermittelt man die Werte imin und imax mit

imin = min{i : T [AT [i] ...AT [i] + m − 1] = P },

imax = max{i : T [AT [i] ...AT [i] + m − 1] = P }.

Dann kommt P an allen Positionen AT [i] mit imin ≤ i ≤ imax vor.

Satz 4.12 Ist AT bekannt, so k¨onnen die Vorkommen von P in T mit einem Aufwand von O(|P | log |T | + k) gefunden werden, wobei k die Zahl der Vorkommen von P in T ist. Allgemeiner entspricht einer Position β im Suffixbaum ein zusammenh¨angendes Teil-Array des Suffix-Arrays, das alle Suffixe indexiert, die mit β beginnen. Das heißt, viele Algorithmen auf Suffixb¨aumen k¨onnen mit einem zus¨atzlichen logarithmischen Faktor auf Suffix-Arrays simuliert werden.

4.5.2 L¨angstes gemeinsames Teilwort Satz 4.13 Das l¨angste gemeinsame Teilwort zweier W¨orter S1, S2 kann mit einem Aufwand von O(|S1| + |S2|) gefunden werden. Beweis. Konstruiere T (S1,S2). Ein Wort α ist genau dann ein gemeinsames Teilwort von S1 und S2, wenn es einen mit α beschrifteten Pfad gibt, der zu einem Blatt mit Beschriftung (1, i) und auch zu einem Blatt mit Beschriftung (2, j) fortgesetzt werden kann. Ist α das l¨angste gemeinsame Teilwort, so kann der Pfad nicht zu einem Pfad mit der eben genannten Eigenschaft erweitert werden, d.h., der mit α beschriftete Pfad muß in einem Knoten enden. Um das l¨angste gemeinsame Teilwort zu ermitteln, muß man den Knoten mit gr¨oßter String- Tiefe finden, in dessen Unterbaum sich sowohl ein Blatt mit Beschriftung (1, i) als auch ein Blatt mit Beschriftung (2, j) befinden. Wir definieren fur¨ jeden Knoten v das Bit-Paar (b1(v), b2(v)) mit b1(v) = true bzw. b2(v) = true genau dann, wenn der Unterbaum von v ein Blatt mit Beschriftung (1, i) bzw. (2, j) enth¨alt. Ist v ein Blatt, so ergibt sich (b1(v), b2(v)) aus der Beschriftung von v.Fur¨ innere Knoten v gilt: _ _ b1(v) = b1(w), b2(v) = b2(w). w ist Kind von v w ist Kind von v

Damit lassen sich die Werte (b1(v), b2(v)) bottom-up in Linearzeit berechnen. ∗ ∗ ∗ Schließlich ermittelt man durch DFS oder BFS den Knoten v mit b1(v ) = b2(v ) = true und maximaler String-Tiefe. 2

92 4.5.3 Ziv-Lempel-Kompression Der Algorithmus von Ziv und Lempel ist eines der gebr¨auchlichsten Verfahren der Datenkom- pression. Bei linearer Laufzeit fur¨ Kompression und Dekompression werden in der Praxis sehr gute Kompressionsraten erreicht. Die hier vorgestellte Variante (LZ77) hat folgende Grundi- dee: Der Text T [1 . . . i] sei bereits komprimiert. Das l¨angste Pr¨afix von T [i + 1 . . . n], das in T [1 . . . i] vorkommt, habe die L¨ange `i und komme zum ersten Mal an der Stelle pi vor. Gilt `i > 0, so kann man den Text T [i + 1 . . . i + `i] durch (pi, `i) kodieren. Gilt `i = 0, so speichert man (0,T [i + 1]).

Beispiel 4.8 Die Lempel-Ziv-Komprimierte fur¨ T = abaababaabaab ist

(0, a)(0, b)(1, 1)(1, 3)(2, 5)(1, 2).

Umgekehrt l¨aßt sich die Dekompression sehr einfach mit linearem Aufwand ausfuhren.¨ Sei der Text T [1 . . . i] bereits dekomprimiert. Ist das n¨achste Zeichen der Komprimierten (p, `) mit p > 0, so h¨angt man den Text T [p . . . p+`−1] an. Ist das n¨achste Zeichen der Komprimierten (0, x) mit x ∈ Σ, so h¨angt man den Text x an. Mit Hilfe von Suffixb¨aumen kann man den Ziv-Lempel-Algorithmus als Linearzeitalgo- rithmus implementieren.

Satz 4.14 Der Ziv-Lempel-Algorithmus (LZ77) kann so implementiert werden, daß die Lauf- zeit O(n) fur¨ einen Text der L¨ange n betr¨agt.

Beweis. Sei der Suffixbaum von S[1 . . . i] bekannt. Dann kann (pi, `i) bestimmt werden, indem man den l¨angsten Pfad ermittelt, der mit einem Pr¨afix von S[i + 1 . . . n] beschriftet ist. Der Aufwand dafur¨ betr¨agt O(`i). Den Gesamtaufwand erh¨alt man durch Aufsummierung uber¨ alle Positionen i, fur¨ die (pi, `i) zu bestimmen ist. Da sich die n¨achste Position als i+max{`i, 1} ergibt, betr¨agt der Gesamtaufwand O(n). Gut geeignet fur¨ die Implementierung ist der Online-Algorithmus von Ukkonen. 2

4.5.4 Burrows-Wheeler-Transformation Eine wichtige Anwendung von Suffix-Arrays ist die Burrows-Wheeler-Transformation. Ein Wort S wird eineindeutig in ein Wort S0 transformiert. Wie wir sehen werden, enth¨alt in typischen Texten das Wort S0 große Bl¨ocke gleicher Buchstaben und kann gut komprimiert werden.

Definition 4.8 Es sei S ∈ Σ∗ ein Wort mit |S| = n und # ∈/ Σ ein Sonderzeichen. Die Burrows-Wheeler-Transformierte von S ist das Wort S0 der L¨ange (n + 1) mit S0[j] = S[AS[j] − 1], wobei S[0] := #.

Beispiel 4.9 Fur¨ S = abcabca erhalten wir:

AS = (8, 7, 4, 1, 5, 2, 6, 3), S0 = a c c # a a b b

93 Eine alternative Interpretation ist die folgende: Schreibe die zyklischen Permutationen von S# in lexikografischer Reihenfolge untereinander. Die letzte Spalte ist die Burrows-Wheeler- Transformierte. In unserem Beispiel S = abcabca erhalten wir:

#abcabc a a#abcab c abca#ab c abcabca # bca#abc a bcabca# a ca#abca b cabca#a b

Satz 4.15 Die Burrows-Wheeler-Transformierte von S kann in O(n) Schritten ermittelt wer- den.

Satz 4.16 Ein Wort S kann aus seiner Burrows-Wheeler-Transformierten in O(n) Schritten ermittelt werden. Beweis. Von der Matrix der zyklischen Permutationen sind die erste Spalte S (Symbole der Transformierten S0 in lexikografischer Ordnung) und die letzte Spalte (die Burrows-Wheeler- Transformierte S0) bekannt. Man bestimmt S[i] induktiv wie folgt. i = 1: Die Position von # in S0 sei j. Dann ist S[1] = S[j]. i ← i + 1: Im Schritt i werde S[i] an der Stelle von S gefunden, an der zum j-ten Mal der Buchstabe S[i] in S vorkommt. Dann findet man S[i + 1] an der Stelle von S, an der zum j-ten Mal der Buchstabe S[i] in S0 vorkommt.

Um die Rucktransformation¨ in Linearzeit durchzufuhren¨ definieren wir P • ein Array P uber¨ der Indexmenge Σ ∪ {#} mit P [a] = |S#|b, b

• fur¨ a ∈ Σ ∪ {#} das Array Va der Gr¨oße |S#|a mit 0 0 Va[i] = j : ⇐⇒ S [j] = a ∧ |S [1 . . . j]|a = i.

0 P und Va k¨onnen in linearer Zeit bestimmt werden. Ist in Schritt i die Position j von S und 0 S erreicht und gilt S[i] = S[j] = a, so wird in Schritt i + 1 die Position Va[j − P [a]] von S und S erreicht. 2

Beispiel 4.10 Wir fuhren¨ fur¨ acc#aabb die Rucktransformation¨ aus. Das # in S0 steht unter dem dritten a (1), das dritte a in S0 steht unter dem zweiten b (2), das zweite b in S0 steht unter dem zweiten c (3), usw. S : # a a a b b c c S0 : a c c # a a b b 8 7 4 1 5 2 6 3 Die Rucktransformation¨ ergibt damit abcabca#.

94 Der Wert der Burrows-Wheeler-Transformation besteht darin, daß in der Transformierten oft das gleiche Symbol hintereinander auftritt. Genauer: Tritt xβ k1-mal und β k2-mal in S auf, so enth¨alt die Transformierte einen Block der L¨ange k2, in dem k1-mal das Symbol x vorkommt.

Beispiel 4.11 Enth¨alt ein Text das Wort Algorithmus 20 Mal und das Wort Logarithmus 5 Mal und keine weiteren Vorkommen von ithmus, so enth¨alt die Transformierte z.B.

• einen Block der L¨ange 25 mit r,

• einen Block der L¨ange 25 mit 20 o und 5 a,

• einen Block der L¨ange 20 mit g.

Das Auftreten von langen Bl¨ocken gleicher L¨ange kann in anderen Kompressionsverfahren (z.B. Move-to-front-Verfahren) ausgenutzt werden. Ein bekannte Implementierung ist das Programm bzip2.

95 Literaturverzeichnis

[1] Alberto Apostolico and Zvi Galil, Pattern Matching Algorithms. Oxford University Press, New York, 1997. [2] Thomas Cormen, Charles Leiserson, and Ronald Rivest. Introduction to Algorithms. MIT Press, 1990. [3] Maxime Crochemore and Wojciech Rytter, Text Algorithms. Oxford University Press, New York, 1994. [4] Maxime Crochemore and Wojciech Rytter, Juwels of Stringology. World Scientific, Sin- gapore, 2002. [5] Maxime Crochemore, Christophe Hancart, et Thierry Lecroq, Algorithmique du texte. Vuibert, Paris, 2001. [6] Dan Gusfield, Algorithms on Strings, Trees, and Sequences. Cambridge University Press, New York, 1997. [7] Volker Heun, Grundlegende Algorithmen. Vieweg Verlag, 2000. [8] John Hopcroft, Rajeev Motwani und Jeffrey Ullman, Einfuhrung¨ in die Automatentheo- rie, Formale Sprachen und Komplexit¨atstheorie. Pearson Studium, Munchen,¨ 2002. [9] Juha K¨arkk¨ainen und Peter Sanders, Simple linear work suffix array construction. In: Proceedings of ICALP, 2003. [10] Hans Werner Lang, Algorithmen in Java. Oldenbourg Verlag, 2003. [11] Jesper Larsson, Structures of String Matching and Data Compression, Dissertation, Lund University, Sweden, 1999. http://www.cs.lth.se/~jesper/research.html [12] Gonzalo Navarro and Mathieu Raffinot, Flexible Pattern Matching in Strings – Practical on-line search algorithms for texts and biological sequences, Cambridge University Press, 2002. http://www.dcc.uchile.cl/~gnavarro/FPMbook/ [13] G.A. Stephen, String Searching Algorithms. World Scientific, Singapore, 1994. [14] W. F. Smyth, Computing Patterns in Strings, Pearson Addison Wesley (UK), 2003. [15] A.C. Yao, The complexity of pattern matching for a random string, SIAM Journal on Computing, 8(3):368-387, 1979.

96