ppt

Werbung
Referat zum Bau von Suffix
Baeumen
Autoren:
Hanna Kraeusel
Axel Block
Magnus Brockschmidt
Prozeduraler Algorithmus
Konstruiere T1;
for (i=1; i<m; i++) {
/*Beginn von Phase i+1 */
Prozeduraler Algorithmus
Konstruiere T1;
for (i=1; i<m; i++) {
/*Beginn von Phase i+1 */
for (j=1; j<=j+1;j++) {
/*Beginn von der j-ten Erweiterung*/
Prozeduraler Algorithmus
Konstruiere T1;
for (i=1; i<m; i++) {
/*Beginn von Phase i+1 */
for (j=1; j<=i+1;j++) {
/*Beginn von der j-ten Erweiterung*/
Finde das Ende des Pfades mit Label S[j..i];
Falls noetig, erweitere den Pfad durch S[i+1];
}
}
Erweiterungsregeln
1.
ß endet in einem Blatt. Dann füge [i+1] zum
Kantenlabel hinzu.
Erweiterungsregeln
1.
2.
ß endet in einem Blatt. Dann füge [i+1] zum
Kantenlabel hinzu.
Es gibt keinen Pfad am Ende von ß, der mit S[i+1]
weitergeht, aber mindestens ein anderer Pfad geht
weiter. Dann füge eine neue Kante mit Label S[i+1]
ein. Dazu muß ein neuer Knoten erzeugt werden,
wenn ß mitten in einer Kante endet. Gib dem
neuen Blatt Nummer j.
Erweiterungsregeln
1.
2.
3.
ß endet in einem Blatt. Dann füge [i+1] zum
Kantenlabel hinzu.
Es gibt keinen Pfad am Ende von ß, der mit S[i+1]
weitergeht, aber mindestens ein anderer Pfad geht
weiter. Dann füge eine neue Kante mit Label S[i+1]
ein. Dazu muß ein neuer Knoten erzeugt werden,
wenn ß mitten in einer Kante endet. Gib dem
neuen Blatt Nummer j.
Es gibt einen Pfad am Ende von ß, der mit S[i+1]
weitergeht. In diesem Fall ist ßS[i+1] schon im
Baum und wir tun nichts.
Beispiel: Wir wollen den Suffix
Baum des Strings abcabcabacdba
erzeugen.
Um den Baum zu bilden, muss in der Phase i der Baum Bi
in den Baum Bi+1 umgewandelt werden.
Wir beschreiben jede Phase und zeichnen den Baum immer,
wenn die Phase beendet ist.
Einfügen von a
Gesamter String: a
a
Es ist nur a Einzufügen!
(Regel 2)
Einfügen von b
Gesamter String: ab
a
b
In der ersten Erweiterung fügen
wir ein b an das vorhandene Blatt
an. (Regel 1)
Einfügen von b
Gesamter String: ab
a
b
b
In der ersten Erweiterung fügen
wir ein b an das vorhandene Blatt
an. (Regel 1)
Die zweite Erweiterung konstruiert
einen neuen Ast mit der Bezeichnung
b. (Regel 2)
Einfügen von b
Gesamter String: ab
a
b
b
In der ersten Erweiterung fügen
wir ein b an das vorhandene Blatt
an. (Regel 1)
Die zweite Erweiterung konstruiert
einen neuen Ast mit der Bezeichnung
b. (Regel 2)
Jetzt stehen alle Suffixe des Strings ab im Baum.
Einfügen von c
Gesamter String: abc
a
b
c
b
c
c
In den ersten beiden Erweiterungen
fügen wir ein c an die vorhandenen
Blätter an.
Die dritte Erweiterung konstruiert
einen neuen Ast mit der Bezeichnung
c.
Jetzt sind alle Suffixe von abc im Baum
enthalten.
Einfügen von a
Gesamter String: abca
a
b
c
a
b
c
a
c
a
In den ersten drei Erweiterungen fügen
wir ein a an die vorhandenen Blätter
an.
Die vierte Erweiterung muss
keinen neuen Ast kreieren, da a bereits
Als Präfix von abca vorhanden ist. (Regel 3)
Jetzt sind alle Suffixe von abca im Baum
enthalten.
Einfügen von b
Gesamter String: abcab
a
b
c
a
b
b
c
a
b
c
a
b
Diese Phase ist synchron zur vorherigen
Phase.
Einfügen von c
Gesamter String: abcabc
a
b
c
a
b
c
b
c
a
b
c
c
a
b
c
Auch hier ist nichts anderes zu tun.
Man erkennt, dass der Suffix Baum
keine weiteren Äste hinzufügt, wenn
die neuen Character nur Teilstrings
des gesamten Strings bilden.
Einfügen von a
Gesamter String: abcabca
a
b
c
a
b
c
a
b
c
a
b
c
a
c
a
b
c
a
Nur anhängen von a an die
vorhandenen Äste nötig!
Einfügen von b
Gesamter String: abcabcab
a
b
c
a
b
c
a
b
b
c
a
b
c
a
b
c
a
b
c
a
b
Jetzt wird noch b an die vorhandenen
Äste angefügt!
Einfügen von a
Gesamter String: abcabcaba
a
b
c
a
b
c
a
b
a
b
c
a
b
c
a
b
a
c
a
b
c
a
b
a
Erweiterung 1 bis 3: Wie zuvor auch fuegen wir ein a
an alle Aeste an.
Einfügen von a
Gesamter String: abcabcaba
a
b
c
a
b
c
a
b
a
a
b
c
a
b
c
a
b
a
c
a
b
c
a
b
a
Erweiterung 4: Jetzt muss der String abcaba gefunden werden.
Von der Wurzel laufen wir abcab runter und fuegen ein a an.
Einfügen von a
Gesamter String: abcabcaba
a
b
c
a
b
c
a
b
a
a
b
c
a
b
c
a
b
a
c
a
b
c
a
b
a
Erweiterung 4: Jetzt muss der String abcaba gefunden werden.
Von der Wurzel laufen wir abcab runter und fuegen ein a an.
Einfügen von a
Gesamter String: abcabcaba
a
b
c
a
b
c
a
b
a
a
a
b
c
a
b
c
a
b
a
a
a
c
a
b
c
a
b
a
a
Einfügen von c
Gesamter String: abcabcabac
a
b
c
a
b
c
a
b
a
c
a
c
a
c
b
c c
a
b
c
a
b
a
c
a
c
a
c
c
a
b
c
a
b
a
c
a
c
Einfügen von d
Gesamter String: abcabcabacd
a
b
c
a
b
c
a
b
a
c
d
a
c
d
a
c
d
c
d
b
c
a
b
c
a
b
a
c
d
a
c
d
a
c
d
c
a
b
c
a
b
a
c
d
d
d
a
c
d
Einfügen von b
Gesamter String: abcabcabacdb
a
b
c
a
b
c
a
b
a
c
d
b
a
c
d
b
a
c
d
b
c
d
b
b
c
a
b
c
a
b
a
c
d
b
a
c
d
b
a
c
d
b
c
a
b
c
a
b
a
c
d
b
d
b
a
c
d
b
d
b
Einfügen von a
Gesamter String: abcabcabacdba
a
b
c
a
b
c
a
b
a
c
d
b
a
a
c
d
b
a
c
a d
c b
d a
b
a
b
c
a
b
c
a
b
a
c
d
b
a
a
c
d
b
a
a
c
d
b
a
c
a
b
c
a
b
a
c
d
b
a
a
c
d
b
a
d
b
a
d
b
a
Definition von Suffix Links
• Knoten v hat die
Beschriftung
x (wobei x ein einzelner Character sei).
 ist möglicherweise leer.
Definition von Suffix Links
• Knoten v hat die
Beschriftung
x (wobei x ein einzelner Character sei).
 ist möglicherweise leer.
• Knoten s(v) hat die Beschriftung 
Definition von Suffix Links
• Knoten v hat die
Beschriftung
x (wobei x ein einzelner Character sei).
 ist möglicherweise leer.
• Knoten s(v) hat die Beschriftung 
• Jetzt heißt die Kante v  s(v) ein
Suffix-Link.
Gibt es für jeden Knoten v ein
Suffix Link zu s(v)?
Beobachtung
Wenn der Knoten v als neuer innerer Knoten während der
Verarbeitung von Erweiterung j in Phase i durch den bisherigen
Algorithmus eingesetzt wird, und wenn v die Markierung x trägt,
dann gilt eine der beiden Aussagen:
1.
2.
Der Weg mit Beschriftung  endet in einem bereits vorhandenen
inneren Knoten w = s(v).
Ein neuer Knoten s(v) wird bei der Verarbeitung von Extension j+1
in Phase i angelegt und s(v) hat  als Beschriftung.
Beweis
• Das Hinzufügen eines Knoten v kann nur in
der Erweiterungsregel 2 passiert sein.
• Dann gibt es, neben der Verbindung zum
neuen Blatt, auch einen weiteren von v
ausgehenden Weg, der den Buchstaben y als
ersten besitzen möge.
Es treten zwei Fälle auf
Fall1:Der gegenwärtige Baum besitzt neben xy einen weiteren Weg von
•
•
der Wurzel beginnend mit der Beschriftung xz, wobei z ein beliebiger String
aus dem Suffix sei, und z  y.
Jetzt gibt es Suffixe mit den Präfixen xy und xz, also auch mit y und z.
Deswegen besitzt der Baum einen Knoten s(v) mit der Beschriftung .
Fall2: Der gegenwärtige Baum besitzt keinen weiteren Weg wie in Fall1, dann
wird in der Verarbeitung von S(j+1..i) ein neuer innerer Knoten s(v) angelegt,
der die Beschriftung  hat, weil es Suffixe mit den Präfixen y und S(i+1)
gibt.
Lemma
• Bei Ukkonens Algorithmus hat jeder
implizite Suffix Baum für jeden neuen
inneren Knoten einen Suffix Link nach dem
Ende der nächsten Erweiterung.
Beweis
• Der Beweis dieses Lemmas ist induktiv.
• Sie ist wahr für B1, weil B1 noch keine Knoten
besitzt.
• Da in der letzten Erweiterung einer Phase keine
neuen Knoten eingefügt werden, denn in dieser
Phase ist der zu behandelnde String nur ein
einzelner Character, sind am Ende der Phase i alle
Knoten mit Suffix Links belegt und zu Beginn der
Phase i+1 gilt ebenfalls die Aussage.
Single extension algorithm
(SEA)
Begin
• Finde Knoten v über dem Ende von S[j-1..i].
Laufe eine Kante vom Ende von S[j-1..i] hoch.
Sei nun y der String zwischen dem Ende von S[j-1..i] und
v.
Single extension algorithm
(SEA)
Begin
• Finde Knoten v über dem Ende von S[j-1..i].
Laufe eine Kante vom Ende von S[j-1..i] hoch.
Sei nun y der String zwischen dem Ende von S[j-1..i] und
v.
• Wenn v nicht die Wurzel ist, gehe den Suffix Link entlang
nach s(v). Klettere den Baum herunter an dem Ast des
Strings y.
Wenn v die Wurzel ist, folge S[j..i]
von der Wurzel.
Single extension algorithm
(SEA)
Begin
• Finde Knoten v über dem Ende von S[j-1..i].
Laufe eine Kante vom Ende von S[j-1..i] hoch.
Sei nun y der String zwischen dem Ende von S[j-1..i] und
v.
• Wenn v nicht die Wurzel ist, gehe den Suffix Link entlang
nach s(v). Klettere den Baum herunter an dem Ast des
Strings y.
Wenn v die Wurzel ist, folge S[j..i]
von der Wurzel.
• Sorge gemäss den Erweiterungsregeln dafür, dass der
String S[j..i]S(i+1) im Baum enthalten ist.
Single extension algorithm
(SEA)
Begin
• Finde Knoten v über dem Ende von S[j-1..i].
Laufe eine Kante vom Ende von S[j-1..i] hoch.
Sei nun y der String zwischen dem Ende von S[j-1..i] und v.
• Wenn v nicht die Wurzel ist, gehe den Suffix Link entlang nach s(v).
Klettere den Baum herunter an dem Ast des Strings y.
Wenn v die Wurzel ist, folge S[j..i] von der Wurzel.
• Sorge gemäss den Erweiterungsregeln dafür, dass der String
S[j..i]S(i+1) im Baum enthalten ist.
• Wenn in Erweiterung j-1 ( nach Erweiterungsregel 2) ein Knoten w
erzeugt wurde, dann muss der String  das Ende des Suffix Links s(w)
sein. Erzeuge einen Link (w,s(w)) von w nach s(w).
End.
Beispiel: Wir wollen den Suffix
Baum des Strings abcabcabacdb
mit Hilfe von Suffixlinks
erzeugen.
Um den Baum zu bilden, muss in der Phase i der Baum Bi
in den Baum Bi+1 umgewandelt werden.
Einfügen von a
Gesamter String: a
Es ist nur a Einzufügen!
a
In den ersten Phasen sind die
Suffix Links noch nicht wichtig,
da noch keine Knoten vorhanden
Sind.
Einfügen von b
Gesamter String: ab
a
b
In der ersten Erweiterung fügen
wir ein b an das vorhandene Blatt
an.
Einfügen von b
Gesamter String: ab
a
b
b
In der ersten Erweiterung fügen
wir ein b an das vorhandene Blatt
an.
Die zweite Erweiterung konstruiert
einen neuen Ast mit der Bezeichnung
b.
Einfügen von b
Gesamter String: ab
a
b
b
In der ersten Erweiterung fügen
wir ein b an das vorhandene Blatt
an.
Die zweite Erweiterung konstruiert
einen neuen Ast mit der Bezeichnung
b.
Jetzt stehen alle Suffixe des Strings ab im Baum.
Einfügen von c
Gesamter String: abc
a
b
c
b
c
c
In den ersten beiden Erweiterungen
fügen wir ein c an die vorhandenen
Blätter an.
Die dritte Erweiterung konstruiert
einen neuen Ast mit der Bezeichnung
c.
Jetzt sind alle Suffixe von abc im Baum
enthalten.
Einfügen von a
Gesamter String: abca
a
b
c
a
b
c
a
c
a
In den ersten drei Erweiterungen fügen
wir ein a an die vorhandenen Blätter
an.
Die vierte Erweiterung muss
keinen neuen Ast kreieren, da a bereits
Als Präfix von abca vorhanden ist.
Jetzt sind alle Suffixe von abca im Baum
enthalten.
Einfügen von b
Gesamter String: abcab
a
b
c
a
b
b
c
a
b
c
a
b
Diese Phase ist synchron zur vorherigen
Phase.
Einfügen von c
Gesamter String: abcabc
a
b
c
a
b
c
b
c
a
b
c
c
a
b
c
Auch hier ist nichts anderes zu tun.
Man erkennt, dass der Suffix Baum
keine weiteren Äste hinzufügt, wenn
die neuen Character nur Teilstrings
des gesamten Strings bilden.
Einfügen von a
Gesamter String: abcabca
a
b
c
a
b
c
a
b
c
a
b
c
a
c
a
b
c
a
Nur anhängen von a an die
vorhandenen Äste nötig!
Einfügen von b
Gesamter String: abcabcab
a
b
c
a
b
c
a
b
b
c
a
b
c
a
b
c
a
b
c
a
b
Jetzt wird noch b an die vorhandenen
Äste angefügt!
Einfügen von a
Gesamter String: abcabcaba
a
b
c
a
b
c
a
b
a
b
c
a
b
c
a
b
a
c
a
b
c
a
b
a
In dieser Phase
kommen die
Suffix Links
erst richtig ins
Spiel.
Erweiterung 1 bis 3: Wie zuvor auch fuegen wir ein a
an alle Aeste an.
Einfügen von a
Gesamter String: abcabcaba
a
b
c
a
b
c
a
b
a
a
b
c
a
b
c
a
b
a
c
a
b
c
a
b
a
Diese Erweiterung
erzeugt einen Knoten,
der noch keinen Suffix Link
hat, aber wir wissen, dass
dieser in der naechsten
Erweiterung
hinzugefuegt wird.
Erweiterung 4: Jetzt muss der String abcaba eingefuegt werden.
Von der Wurzel laufen wir abcab runter und fuegen ein a an.
Einfügen von a
Gesamter String: abcabcaba
a
b
c
a
b
c
a
b
a
a
b
c
a
b
c
a
b
a
a
c
a
b
c
a
b
a
Diese Erweiterung
erzeugt einen Suffix Link.
Der neue Knoten ist allerdings
noch nicht weiterverlinkt,
was wieder in der naechsten
Erweiterung passieren
wird.
Erweiterung 5: Jetzt muss der String bcaba eingefuegt werden.
Von der Wurzel laufen wir bcab runter und fuegen ein a an.
Einfügen von a
Gesamter String: abcabcaba
a
b
c
a
b
c
a
b
a
a
b
c
a
b
c
a
b
a
a
c
a
b
c
a
b
a
Diese Erweiterung
erzeugt wie zuvor
einen Suffix Link.
a
Erweiterung 6: Jetzt muss der String caba eingefuegt werden.
Von der Wurzel laufen wir cab runter und fuegen ein a an.
Einfügen von a
Gesamter String: abcabcaba
a
b
c
a
b
c
a
b
a
a
a
b
c
a
b
c
a
b
a
a
c
a
b
c
a
b
a
Diese Erweiterung
erzeugt wie zuvor
einen Suffix Link.
a
Erweiterung 7: Jetzt muss der String aba eingefuegt werden.
Von der Wurzel laufen wir ab runter und fuegen ein a an.
Einfügen von a
Gesamter String: abcabcaba
a
b
c
a
b
c
a
b
a
a
a
b
c
a
b
c
a
b
a
a
a
c
a
b
c
a
b
a
Diese Erweiterung
erzeugt wie zuvor
einen Suffix Link.
a
Der Suffix Link
des neuen Knotens
fuehrt zur Wurzel,
da b nur noch ein
einzelner Character
ist und α ist in
diesem Fall ein
leerer String.
Erweiterung 8: Jetzt muss der String ba eingefuegt werden.
Von der Wurzel laufen wir b runter und fuegen ein a an.
Einfügen von a
Gesamter String: abcabcaba
a
b
c
a
b
c
a
b
a
a
a
b
c
a
b
c
a
b
a
a
a
c
a
b
c
a
b
a
a
Erweiterung 9: Jetzt muss lediglich noch der Character a
eingefuegt werden. Dieser ist allerdings schon vorhanden.
Einfügen von a
Gesamter String: abcabcaba
a
b
c
a
b
c
a
b
a
a
a
b
c
a
b
c
a
b
a
a
a
c
a
b
c
a
b
a
a
Unser Baum ist jetzt vollstaendig verlinkt und die Phase ist beendet.
Einfügen von c
Gesamter String: abcabcabac
Wir wissen, dass abcabcaba
der laengste String im Baum
ist. Wir laufen diesen runter
und fuegen dort ein c an.
a
b
c
b
c
a
a
c
a
a
b
a
b
c
a
b
c
a
a
c
a
a
b
a
b
a
b
a
a
c
Erweiterung 1: Die erste Erweiterung ist immer speziell.
Wir muessen den String abcabcabac einfuegen.
Einfügen von c
Gesamter String: abcabcabac
Wir wissen, dass der erste
Knoten ueber dem laengsten
String im Baum ein Suffix link
hat. Wir laufen vom laengsten
Blatt hoch bis zum besagten
Suffix Link.
Von da gehen wir
a
die gleiche
Bezeichnug
wieder runter
und fuegen
dort ein c an.
a
b
c
b
c
a
a
c
a
a
b
a
b
c
b
c
a
a
c
a
a
b
a
b
a
b
a
a
c
c
Erweiterung 2:Wir muessen den String bcabcabac einfuegen.
Wir nutzen den Suffix Link.
Einfügen von c
Gesamter String: abcabcabac
Wir laufen von der Position,
wo wir in Erweiterung 2 das
c eingefuegt haben, hoch bis
zu dem Suffix link.
Von da gehen wir die gleiche
Bezeichnug
wieder runter, die
a
wir hochgegangen
sind, und fuegen
dort ein c an.
a
b
c
b
c
a
a
c
a
a
b
a
b
c
b
c
a
a
c
a
a
b
a
b
a
b
a
c
a
c
c
Erweiterung 3:Wir muessen den String cabcabac einfuegen.
Wir nutzen wieder den Suffix Link.
Einfügen von c
Gesamter String: abcabcabac
Wir laufen von der Position,
wo wir in Erweiterung 3 das
c eingefuegt haben, hoch bis
zu dem Suffix link.
Von da gehen wir die gleiche
Bezeichnug
wieder runter, die
a
wir hochgegangen
sind, und fuegen
dort ein c an.
a
b
c
b
c
a
a
c
a
a
b
a
b
c
b
c
a
a
c
a
a
b
a
c
b
a
b
a
c
a
c
c
Erweiterung 4:Wir muessen den String abcabac einfuegen.
Wir nutzen den zustaendigen Suffix Link.
Einfügen von c
Gesamter String: abcabcabac
Wir laufen von der Position,
wo wir in Erweiterung 4 das
c eingefuegt haben, hoch bis
zu dem ersten Suffix link.
Von da gehen wir das a
runter, das wir
auch hochgegangen
a
sind, und fuegen
dort ein c an.
a
b
c
b
c
a
a
c
a
a
b
a
b
c
b
c
a
a
c
a
a
c
b
a
c
b
a
b
a
c
a
c
c
Erweiterung 5: Wir muessen den String bcabac einfuegen.
Jetzt nehmen wir den ersten Suffix Link.
Einfügen von c
Gesamter String: abcabcabac
Wir laufen von der Position,
wo wir in Erweiterung 5 das
c eingefuegt haben, hoch bis
zu dem ersten Suffix link.
Von da gehen wir das a
runter, das wir
auch hochgegangen
a
sind, und fuegen
c
dort ein c an.
a
b
c
b
c
a
a
c
a
a
b
a
b
c
b
c
a
a
c
a
a
c
b
a
c
b
a
b
a
c
a
c
c
Erweiterung 6: Wir muessen den String cabac einfuegen.
Dies passiert wie in Erweiterung 5.
Einfügen von c
Gesamter String: abcabcabac
Wir laufen von der Position,
wo wir in der vorherigen
Erweiterung das c eingefuegt
haben, hoch bis zu dem ersten
Suffix link.
Von da gehen wir
das a runter,
a
das wir
c
auch hochgegangen
sind, und fuegen
dort ein c an.
a
b
c
b
c
a
a
c
a
a
c
b
a
c
b
c
b
c
a
a
c
a
a
c
b
a
c
b
a
b
a
c
a
c
c
Erweiterung 7 und 8: Wir muessen den String abac und bac einfuegen.
Diese Vorgaenge sind ebenfalls wie in Erweiterung 5.
Einfügen von c
Gesamter String: abcabcabac
Wir laufen von der Position,
wo wir in der vorherigen
Erweiterung das c eingefuegt
haben, hoch bis zu dem ersten
Suffix link, hier die Wurzel.
Von da gehen wir
das a runter,
a
das wir
c
auch hochgegangen
sind, und fuegen
dort einen neuen
Ast fuer das c an.
Es entsteht ein neuer Suffix
Link zur Wurzel.
a
b
c
b
c c
a
a
c
a
a
c
b
a
c
b
c
b
c
a
a
c
a
a
c
b
a
c
b
a
b
a
c
a
c
c
Erweiterung 9: Wir muessen den String ac einfuegen.
Einfügen von c
Gesamter String: abcabcabac
a
b
c
b
c c
a
a
c
a
a
c
b
a
c
b
c
a
b
c
a
a
c
c
a
a
c
b
a
c
b
a
b
a
c
a
c
c
Erweiterung 10: Wir muessen den String c einfuegen.
Dieser existiert allerdings bereits als Praefix im Baum.
Einfügen von c
Gesamter String: abcabcabac
a
b
c
b
c c
a
a
c
a
a
c
b
a
c
b
c
a
b
c
a
a
c
c
a
a
c
b
a
c
b
a
b
a
c
a
c
c
Phase ist beendet und der Baum ist vollstaendig verlinket.
Einfügen von d
Gesamter String: abcabcabacd
a
b
c
a
b
c
a
b
a
c
d
c
a
c
a
c
b
c
a
b
c
a
b
a
c
a
c
a
c
c
a
b
c
a
b
a
c
Der gesuchte String ist der
Laengste. Wir fuegen d ein
und merken uns die Position.
a
c
Erweiterung 1: abcabcabacd muss eingefuegt werden.
Es geht ebenso wie in der Phase zuvor!
Einfügen von d
Gesamter String: abcabcabacd
a
b
c
a
b
c
a
b
a
c
d
Von der gemerkten Position
gehen wir bis zum Suffix Link
hoch, diesen entlang und an der
Stelle die gleiche Bezeichnung
wieder herunter!
b
c
c c
a
a
a
a
c
b
c
b
c
a
c
a
a
c
a
a
c
b
c
b
a
a
c
c
d
Erweiterung 2: bcabcabacd muss eingefuegt werden.
Es geht ebenso wie in der Phase zuvor!
Einfügen von d
Gesamter String: abcabcabacd
a
b
c
a
b
c
a
b
a
c
d
Von der gemerkten Position
gehen wir jeweils bis zum
Suffix Link hoch, diesen
entlang und an der Stelle die
gleiche Bezeichnung
herunter!
a wieder
Wir nutzen fuer
c diese drei Schritte
die markierten Links
und fuegen die
gelben d’s ein.
b
c
c c
a
a
a
a
c
b
c
b
c
c
a
a
a
a
c
b
c
b
d
a
d
a
c
c
d
d
Erweiterung 3-5: cabcabacd, abcabacd, bcabacd
mussen eingefuegt werden.
Einfügen von d
Gesamter String: abcabcabacd
a
b
c
a
b
c
a
b
a
c
d
Von der gemerkten Position
gehen wir jeweils bis zum
Suffix Link hoch, diesen
entlang und an der Stelle die
gleiche Bezeichnung
herunter!
a wieder
Wir nutzen fuer
c diese drei Schritte
markierten Links
d die
und fuegen die
gelben d’s ein.
b
c
c c
a
a
a d a
c
b
c
b
d
c
d
c
a
a
a
a
c
b
c
b
d
a
d
a
c
c
d
d
Erweiterung 6-9: cabacd, abacd, bacd, acd
mussen eingefuegt werden.
Einfügen von d
Gesamter String: abcabcabacd
a
b
c
a
b
c
a
b
a
c
d
c
a d
c
d
a
c
d
b
c
a
b
c
a
b
a
c
d
a
c
d
a
c
d
c
a
b
c
a
b
a
c
d
d
a
c
d
Jetzt gehen wir ueber
den Suffixlink zur
Wurzel, laufen ein c
wieder runter, weil wir
das auch hochgelaufen
sind, und fuegen einen
neuen Ast fuer das d
ein.
Es entsteht ein neuer
Suffix Link zur Wurzel.
Erweiterung 9: cd muss eingefuegt werden.
Einfügen von d
Gesamter String: abcabcabacd
a
b
c
a
b
c
a
b
a
c
d
c
a d
c
d
a
c
d
b
c
a
b
c
a
b
a
c
d
a
c
d
a
c
d
c
a
b
c
a
b
a
c
d
d
d
a
c
d
Jetzt gehen wir ueber
Den neuen Suffixlink zur
Wurzel, laufen ein c
wieder runter, weil wir
das auch hochgelaufen
sind, und fuegen einen
neuen Ast fuer das d
ein.
Erweiterung 11:d muss eingefuegt werden.
Einfügen von d
Gesamter String: abcabcabacd
a
b
c
a
b
c
a
b
a
c
d
c
a d
c
d
a
c
d
b
c
a
b
c
a
b
a
c
d
a
c
d
a
c
d
c
a
b
c
a
b
a
c
d
d
d
a
c
d
Die Phase ist beendet und der Baum vollstaendig verlinkt.
Einfügen von b
Gesamter String: abcabcabacdb
a
b
c
a
b
c
a
b
a
c
d
b
b
c
c c
a
a
d
a d a
c
b
b
c b b
d
c
a
d
c
a
b
a
c
a b
a
c
b
d
c
b
d
a
b
d
a
b
c
b
c
d
d
b
b
Nach der letzten Phase erhalten wir diesen Baum.
d
b
Trick Nr. 1 Skip/Count Trick
Sinn:
In Phase zwei vom Knoten s(v) dem Label y folgen erfordert eine Zeit t ~ Laenge
von y |y|.
Der Skip/Count Trick reduziert t auf t ~ Anzahl der Knoten in y.
Wir befinden uns an einem Knoten v, und das nun zu erweiternde Suffix hat ein
Praefix, welches auf abcdefgh endet.
Trick 1
•
•
•
Der Trick ist sehr simpel: Wenn am Knoten s(v) angekommen, suche den Weg aus dem
Knoten, welcher mit dem Anfangsbuchstaben von y beginnt. Wenn y länger ist als der
String an dieser Kante bis zum nächsten Knoten, so springe zum nächsten Knoten. Setze
einen Index auf den |String| + 1. Nun schaue, welche Kante aus diesem Knoten mit dem
|String| + 1 Buchstaben aus y beginnt und springe zum nächsten Knoten usw. Dieses
"Springen" endet, wenn der String an der folgenden Kante länger oder gleich der Länge
von y ist. Dann ist nämlich das Ende von y erreicht und nun wird die entsprechende
Extension Rule angewendet.
Also: Man guckt einfach nach dem Weg, zählt und springt einen Knoten weiter oder
zum Ende.
Aber was ist mit dem Worst Case?
Dem Suffix Link von v nach s(v) folgen, dann soll es den String y = abcdefgh
heruntergehen, um an dessen Ende ein Zeichen anzuhaengen. Der naïve Algorithmus wuerde
Zeichen fuer Zeichen ablaufen.
G ist hier die Laenge des restlichen abzulaufenden Teils von y, I der Index des naechsten
Zeichens.
v
Suffix Link
S(v)
a
b
c
d
String y
e
G = |y| = 8,
f
I = 1,
g
h
i
j
Wir suchen den Buchstaben an diesem Knoten, mit dem y beginnt, also a, gucken, ob an
dieser Kante mehr Buchstaben stehen als y lang ist, hier abcd, also kuerzer, somit springen
wir zum naechsten Knoten. Wenn y kuerzer ist als der String an dieser Kante, waere das
Ende von y erreicht, und wir koennten anfuegen.
x
v
Suffix Link
S(v)
a
b
Aktuelle Position
z
g
c
d
String y
e
G = |y| = 8,
f
I = 1,
g
h
i
j
Nun springen wir direkt
zu diesem Knoten
Nun sind wir an dem Knoten. Wir haben 4 Zeichen uebersprungen, also wird G auf G-4
gesetzt und I auf 1+4. Dann gehts weiter, nach der Kante mit dem 5ten Zeichen von y
suchen und zum naechsten Knoten springen.
x
v
Suffix Link
S(v)
a
b
z
g
c
d
Aktuelle
Position
String y
e
G = G-4 = 4,
f
I = I+4 = 5,
g
h
i
j
Nun springen wir weiter
zu diesem Knoten
Die Laenge des Strings an der naechsten Kante, die mit dem 7ten Zeichen von y beginnt ist
groesser als die Laenge des Restes von y. Das Ende von y liegt also an dieser Kante.
x
v
Suffix Link
S(v)
a
b
z
g
c
d
String y
e
G = G-2 = 2,
f
I = I+2 = 7
g
h
Aktuelle Position.
i
j
Ende von y
Wir haben nun das Ende von y gefunden und koennen das Zeichen, z.B. ein w einfuegen.
x
v
Suffix Link
S(v)
a
b
z
g
c
d
String y
e
f
g
h
i
j
Hier findet sich das Ende
von y, und das Zeichen
kann eingefuegt werden.
W eingefuegt, es geht weiter mit der naechsten Extension.
x
v
Suffix Link
S(v)
a
b
z
g
c
d
String y
e
f
g
h
i
j
w
Hier findet sich nun ein
neuer Knoten und ein Ast
mit Label w.
Definition
Die Tiefe (Knotentiefe) eines Knotens ist die Anzahl der Knoten auf
dem Pfad von der Wurzel bis zu diesem Knoten.
Lemma
Es sei (v, s(v)) irgendein Suffix Link. Dann ist die Knotentiefe von v hoechstens um
1 groesser als die von s(v).
Beweis
•
•
•
•
•
•
Jeder interne Vorfahr von v mit Label xbeta hat einen Link zu einem Knoten
mit Label beta.
xbeta ist ein Präfix des Pfades zu v, so ist beta ein Präfix des Pfades zu s(v)
--> Jeder Link von einem internen Vorfahr von v geht zu einem internen
Vorfahr von s(v).
Und wenn beta nicht leer ist, so ist der Knoten mit dem Label beta ein interner
Knoten. Da die Tiefen zweier Vorfahren von v verschieden sein muessen, hat
jeder Vorfahr von v einen Link zu einem anderen Vorfahren von s(v).
-->Die Tiefe von s(v) ist mindestens 1 (Wurzel) + die Anzahl interner
Vorfahren von v mit längerer Bezeichnung als einem Zeichen.
Den einzigen Vorfahren ohne Gegenstück, den v haben kann, ist der mit nur
einem Zeichen, und nur dann ist die Tiefe von v auch nur 1 groesser als die
von s(v).
Ausschnitt aus dem Suffixbaum fuer den String ALDACFALBALDACTALDACFALBN,
ohne Links.
L D
A
C F
A L
B A
L D
A
C T
A
L D
A C
F A
L B
N
N
A
D
A C
F A
L
B
A
L
D
A
C T
D
A
C F
A
L
D A
C
N
C
F A L
B A L D
A C
T
A
L
A L
B N
N
L
D
A
C
F A
L B
A L
N
D A
C
T
A
L
D
A
C F A
L
B N
F A
L B N
Bei diesen Links ist die Tiefe von v um 1 groesser als die Tiefe von s(v).
S(v)
L D
S(v)
A
S(v)
C F
A L
B A
L D
A
C T
A
L D
A C
F A
L B
N
N
A
D
A C
F A
L
B
A
L
D
A
C T
D
A
C F
A
L
D A
C
N
C
F A L
B A L D
A C
T
A
L
A L
B N
N
L
v
D
A
C
F A
v
L B
A L
v
N
D A
C
T
A
L
D
A
C F A
L
B N
F A
L B N
Bei diesen Links ist die Tiefe von v um 1 kleiner als die Tiefe von s(v).
L D
A
C F
A L
B A
L D
A
C T
A
L D
A C
F A
L B
N
N
A
D
A C
F A
L
v
C
F A L
S(v)
B A L D
B
A
v
A C
T
L
D
A
C T
D
A
C F
A
L
D A
C
N
A
L
A L
B N
S(v)
N
L
D
A
C
F A
L B
A L
N
D A
C
T
A
L
D
A
C F A
L
B N
F A
L B N
Definition
•
Die aktuelle Knotentiefe ist die des zuletzt besuchten Knotens.
Behauptung
Mit diesem Trick dauert jede Phase des Algorithmus O(m).
Beweis
•
•
Es gibt höchstens m Extensions in einer Phase. In einer davon es geht höchstens einen
Knoten hoch zum nächsten Link, den Link entlang, die Knoten herunter und die Regeln
ausführen, evtl auch Link setzen. Wir wissen, daß alles ausser dem Knoten abwärts
gehen konstante Zeit benoetigt. Dieses untersuchen wir anhand der Tiefeveränderung in
einer Phase.
Einen hoch, der Suffix Link erhöht höchstens weiter um einen, es geht also höchstens
zwei rauf, also insgesamt höchstens 2m rauf. Da der Baum aber höchstens m Knoten
haben kann, geht es auf die Phase gesehen höchstens 3m herunter. Es gibt also höchstens
3m downwalks, --> O(m)
Corollar
Es gibt m Phasen mit O(m), also insgesamt O(m*m).
Das ist sehr grob gerechnet und sieht schlecht aus, aber mit ein paar kleinen weiteren
Details erreichen wir O(m).
Ersetzen der Zeichen durch
Indices
Durch die Zeichen an den Kanten nimmt der Baum sehr viel Platz weg. Diese werden nun
durch Indices ersetzt, die Anfang und Ende des Teilstrings im Gesamtstring markieren.
Der Auschnitt aus dem Baum, dieses mal mit Indices.
A L D A C F A L B A L D A C T A L D A C F A L B N
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
2-2
3-5
6 - 10
11
-
25
25 - 25
6 - 10
1
1
11
-
25 - 25
3-3
2
2
6 - 10
11
-
25
25 - 25
3-5
6 - 10
11
25 - 25
-
25
25
Single Phase Algorithm
(SPA)
1. Setze e auf i+1.
2. Führe mit Hilfe vonSuffix-Links
Erweiterungen durch, bis in Erweiterung
j* Regel 3 angewandt wird.
3. Setze ji+1 auf j*-1 und gehe zur nächsten
Phase.
Herunterladen