Suffix Trees und Suffix Arrays

30.Juni 2005. 1 Problembeschreibung und Motivation ..... änlichen Suffixen nebeneinander im Array stehen, ist es sinnvoll binäre Suche zu verwenden. Bei. 5 ...
247KB Größe 8 Downloads 899 Ansichten
Suffix Trees und Suffix Arrays Stefka Penkova

Angel Tchorbadjiiski 30.Juni 2005

1 Problembeschreibung und Motivation Objekt diesem Artikels ist der Substringproblem. Eingabe des Problems P ist eine Zeichenkette S. Ziel ist alle Vor¨ kommen einer gegebenen willkurlichen Zeichenkette q zu finden, wo q Teilkette von S ist. Es wird also eine Datenstruktur D gesucht, die P so repr¨asentiert, dass: (1) D lineare Platzkomplexit¨at hat, (2) D in linearer Zeit hergestellt werden kann, (3) D die Suche von q in S in Zeit O(|m|), wobei m die La¨ nge von q, erlaubt.

2 Suffix Trees 2.1

Definition, Vorstellung des Begriffs

¨ Der Suffix-Baum ist eine Datenstruktur, mit deren Hilfe der Stringmatching-Problem in O(m) Zeit zu l osen ist. ¨ ein Wort der L¨ange m ist das den Baum T mit genau m Bla¨ ttern (1 bis m). Jeder Was ist aber ein Suffix-Baum? Fur innere Knoten von T ausser der Wurzel hat mindestens 2 Nachfolger und jede Kante hat eine nicht leere Beschriftung. Es kann keine Zwei Kanten vom selben Knoten mit dem selben Beschriftung geben. Die wichtigste Eigenschaft der Suffix-B¨aume ist, dass jeder Pfad vom Wurzel bis zu einem Blatt einen Suffix von dem vorgegebenen Wort entspricht.

2.2

Vorgeschichte

Es gibt drei Algorithmen, mit deren Hilfe man einen Suffix-Baum im O(m) Zeit erstellen kann. Der erste Algorithmus wurde im Jahre 1973 vom Weiner erfunden. Einige Jahre sp a¨ ter wurde vom McCreigth einen platzeffizienteren Algorithmus entwickelt. Vor 10 Jahren (1995) entwickelte Ukkonen ein Algorithmus, der konzeptuell unterschiedlich von den 2 obigen ist, aber die Vorteile von McCreight’s Algorithmus hat. Der ist aber auch viel leichter zu erkl a¨ ren/verstehen.

2.3

Strukturaufbau und naiver Algorithmus

¨ jeden String S der L¨ange Es gibt eine wichtige Kleinigkeit - die Definition von Suffix-Baum garantiert nicht, dass f ur ¨ m ein Baum existiert. Man muss noch hinzufugen, dass wenn ein Suffix von S auch ein Pra¨ fix von einem anderen Suffix von S ist, gibt es keinen Suffix-Baum, der von der obigen Definition herzuleiten ist. Deswegen nehmen wir an, dass das letzte Zeichen von S, nur einmal in dem Wort vorkommt. Wenn das nicht der Fall ist, wird am Ende ein ¨ Zeichen (z.B. $) hinzugefugt, das nicht im Wort vorkommt. Der naive Algorithmus zur Konstruktion von einem Suffix-Baum ist der Folgende: Wir nehmen an, dass das Wort ¨ zuerst das ganze Wort in den Baum, also von Index 1 bis S in einem Array gespeichert vorliegt. Schritt 1. Man fugt Index m. ¨ man die Folge i bis m in den Baum. Es ist dabei nur folgende Regel zu beachten: Im Shritt i. (i = 2 . . . m) fugt

1

Abbildung 1: Beispiel - Aachen ¨ - Falls die Indexfolge (der Suffix) [i . . . m] nicht mit einem Pr a¨ fix von einem schon im Baum eingefugten Suffix ¨ beginnt, wird der ganze Suffix [i . . . m], so wie der ist, einfach von der Wurzel in den Baum eingef ugt. ¨ - Falls ein Pr¨afix von [i . . . m] auch ein Pr¨afix von einem anderen Suffix (schon im Baum eingefugt) ist, d.h. dass ¨ ¨ eine oder mehrere Anfangsbuchstaben von beiden Suffixen ubereinstimmen, wird der ubereinstimmende Pfad von der Wurzel verfolgt, bis man das erste Zeichen erreicht, das beide Suffixe unterscheidet. An der Stelle vor ¨ (wenn man sich gerade auf einer Kante befindet - sonst ist diesem Zeichen wird ein neuer Knoten eingefugt ¨ man schon in einem Knoten) und an der Stelle wird eine Kante von dem Knoten zu einem neu hinzugef ugten ¨ Blatt mit Nummer i eingefugt. Die Beschriftung dieser Kante ist der Suffix [i . . . m] ohne den oben genannten Pr¨afix. ¨ das So wird Schritt i so lange iteriert, bis man i = m erreicht hat. Wenn das passiert ist, haben wir den Suffix-Baum f ur Wort S. Der Baum wurde in Zeit O(m2 ) gebildet, die nicht linear ist. Das Ziel war aber nur ein naiver Algorithmus vorzustellen, damit die Idee, die hinter den Suffix-Ba¨ umen steckt, klar wird.

2.4

Ukkonen’s Algorithmus zur Konstruktion - Grundidee und Implementierungsdetails Der Algorithmus von Ukkonen beruht auf den impliziten Suffix-B a¨ umen. Der Unterschied zwischen dieser Art und den normalen Suffix-B¨aumen (wie oben beschrieben) ist, dass hier alle Vorkommen des zus a¨ tzlich ¨ eingefugten Zeichens (z.B. $) entfernt werden. Dann werden zuerst alle Kanten ohne Beschriftung, danach auch alle Knoten, die weniger als 2 Nachfolger haben, vom Baum entfernt. Ukkonen’s Idee ist folgende: Man f a¨ ngt bei 1 an und bildet den impliziten Suffix-Baum T (1). Dieser Suffix-Baum besteht nur aus dem ersten Zeichen im String S. Danach macht man weiter, indem man im Schritt i + 1, i ≥ 1 den impliziten Suffix-Baum T (i + 1) von seinem Vorg¨anger T (i) konstruiert.Das geschieht indem man die Suffixe mit dem n a¨ chsten Zeichen (an Position i + 1) verl¨angert. So hat man nach m Schritten, mit Hilfe der impliziten Suffix-B a¨ ume, den Suffix-Baum ¨ String S konstruiert. fur - Beschleunigungstipps ¨ Es gibt einige Verbesserungen, die auf den oben erl a¨ uterten Algorithmus angewandt werden konnen. 1. Die Erste davon ist die Benutzung von interne Links. Ein Link vom Knoten v zum Knoten s(v) w a¨ re vorhanden, falls der Pfad von v mit x@ und der Pfad zu s(v) mit @ beschriftet ist. Dabei ist x ein einziges Zeichen und @ ist eine Kette von Zeichen, die auch leer sein kann. Mit den Suffix-Links kann man sich ¨ bei der Konstruktion von T (i + 1) von T (i) sparen , wenn man die Links verfolgt. sehr viel Muhe ¨ 2. Kompression der Kantenbeschriftungen gibt die Moglichkeit eine Platzkomplexita¨ t von O(m) zu erreichen. Diese Methode ist eigentlich sehr simpel, sogar intuitiv. Man spart Platz, indem man die Indizes der Anfangs- und Endbuchstaben des Substrings als Beschriftung der Kante benutzt und nicht der Substring selbst. Da der Algorithmus (oder besser das Programm, das den Algorithmus anwendet) eine Kopie des Substrings hat, stellt die Kompression keine Komplikationen dar. 2

Abbildung 2: Suffix-Links - Kurze Zusammenfassug , was erreicht wurde Es werden also m Phasen gebraucht, um den impliziten Suffix-Baum T (m) zu konstruiieren. Der Platzkom¨ plexit¨at ist maximal 2(2m − 1), da maximal 2m − 1 Kanten im Baum vorhanden sein k onnen. Es wird eine zus¨atzliche Umwandlung des impliziten Suffix-Baums in einem normalen Suffix-Baum, d.h. man muss nur ¨ noch den $-Zeichen im Baum einfugen. Wie wir schon wissen, ist das eine zusa¨ tzliche Phase, also haben wir nicht mehr m Phasen, sondern m + 1. Dann ist die Komplexita¨ t also O(m) + O(m + 1) = O(m), also linear ¨ bezuglich |S|.

2.5

Vergleich von Weiner’s, McCreight’s und Ukkonen’s Algorithmen

Die Implementierungsideen, die hinter den drei Algorithmen stehen, sind sehr unterschiedlich, das Ziel ist aber ¨ ein bestimmtes Wort S in O(|S|) Komplexita¨ t zu erzeugen. Wenn man Weiner’s das gleiche - der Suffix-Baum fur ¨ Algorithmus mit dem von Ukkonen vergleicht, kann man sehr viele Ahnlichkeiten feststellen. Sie fangen beide un¨ terschiedlich an - der eine mit dem ersten Buchstaben, der andere mit dem ganzen String, es gibt aber eine Anlichkeit ¨ - beide fugen jedes Mal einen neuen Suffix ein. Die Kompression der Kantenbeschriftungen erweist sich als notwendig in beiden F¨allen, um ein O(m) Komplexit¨at zu erreichen. Weiner benutzt aber noch zwei Vektoren, die er ¨ ”indicator und link vectors” nennt. Das grosste Teil der Implementierung ist fast so effizient wie die von Ukkonen, ¨ diese zus¨atzliche (verglichen mit Ukkonen) Vektoren ist nicht so effizient. Hier Weiner braucht aber mehr Platz fur stellt man fest, das der oben genannte Beschleunigungstipp immer anwendbar ist, da es immer so ein Knoten s(v) gibt, der mit @ beschriftet ist, wenn ein Knoten v mit Beschriftung x@ im Baum ist. McCreight’s und Ukkonen’s Algorithmen sind gleich effizient. Die Implementierungen sehen sich fast gar nicht a¨ hnlich, aber wenn man sich bisschen Gedanken macht, kann man die Verbindung sehen. Eine Verbindung wurde von Ukkonen vorgeschlagen und wurde von Giegerich und Kurtz erkla¨ rt.

2.6

Generalisierte Suffix B¨aume

¨ Dieser Art von Suffix-B¨aume repr¨asentieren mehrere Strings im selben Baum. Es gibt zwei M oglichkeiten so einen Baum zu konstruieren. Hier wird die effektivere Methode von beiden vorgestellt. Nehmen wir o.B.d.A. an, dass wir n Strings haben. Wir fangen mit dem ersten (S1) an und bilden dessen Suffix-Baum. Wenn wir mit dem String S1 ¨ fertig sind, fangen wir mit dem na¨ chsten (S2) an. Es kann sein, dass manche Suffixe von S1 und S2 ubereinstimmen ¨ Man macht weiter, bis alle Suffixe von S2 im Baum sind. So macht man weiter, bis - die werden nur einmal eingefugt. alle Strings im Baum sind. Das Ergebnis ist den Suffix-Baum, in dem alle Suffixe von den gegebenen Strings S1,. . . ,Sn drin sind.

2.7

Anwendungsbeispiele

¨ Die Suffix-B¨aume (inclusiv generalisierte Suffix-Ba¨ ume) , wie auch die Suffix-Array, konnen bei vielen Probleme sehr ¨ nutzlich sein. Das betrifft aber nicht nur solche aus der Informatik, sondern auch biologisch oder chemisch bezogene

3

¨ Probleme. Hier sind einige davon, die mit Hilfe von den oben genannten zwei Strukturen zu l osen sind: Aus der Biologie: - genome alignment - signature selection - Finding and Representing all Tandem Repeats in a String - recognizing DNA contamination Aus der Chemie: - circular string linearization Aus der Informatik: - exact string matching - substring problem for a database of patterns - building a smaller DAG (directed acyclic graph) for exact matching - all-pair suffix-prefix matching - ziv-lempel compression (wird auch zur Kompression von DNA-Sequenz benutzt) - exact matching with wildcards - common substrings of more than two strings

3 Suffix Arrays 3.1

Vorstellung des Begriffs

¨ einen String S ist ein Array pos, in dem die Anfangspositionen von den Suffixen aus S geEin Suffix Array fur ¨ speichert werden. Die Zahlen, die die Anfangspositionen repr a¨ sentieren, befinden sich in dem Array bezuglich der Suffixen in lexikographischer Reihenfolge, z.B. enth a¨ lt pos[2] das Suffix, das lexikographisch an 2. Stelle steht. Suffix ¨ Arrays konnen in O(m) Zeit hergestellt werden und haben Platzkomplexit a¨ t von O(m+1). Die Bin¨are Suche in dieser ¨ Datenstruktur benotigt lineare Zeit. Beispiel 1. Sei t = M ISSISSIP P I, dann sieht das Array pos so aus: pos[0]

=

12 → $

pos[1]

=

11 → I$

pos[2]

=

08 → IP P I$

pos[3]

=

05 → ISSIP I$

pos[4]

=

02 → ISSISSIP P I$

pos[5]

=

01 → M ISSISSIP P I$

pos[6]

=

10 → P I$

pos[7]

=

09 → P P I$

pos[8]

=

07 → SIP P I$

pos[9]

=

04 → SISSIP I$

pos[10]

=

06 → SSIP P I$

pos[11]

=

03 → SSISSIP P I$

4

3.2

Kurz zur Geschichte

¨ Suffix Array wurde zuerst von U. Manber und G. Myers im Jahr 1993 [7] vorgestellt. Sie haben eine neue Die Idee fur Datenstruktur vorgeschlagen, die platzeffizienter als die Suffix Trees war. Eine a¨ hnliche Idee genannt PAT Trees ist im Jahr 1991 im ”Handbook of Algorithms and Data Structures” von Gonnet und Baeza-Yates erschienen.

3.3

Konstruktion von Suffix Array durch Suffix Tree in linearer Zeit

Angenommen das Suffix Tree ST zu dem String S ist gegeben. Das Suffix Array kann aus dem ST durch Anwenden ¨ muss vereinbart werden, wie die Kanten lexikographisch anorddes Tiefensuchealgorithmus erstellt werden. Dafur nen lassen. Eine Kante (v, u) in einem Suffix Tree ist lexikographisch kleiner als eine Kante (v, w) genau dann, wenn das erste Zeichen der Kante (v, u) in der lexikographischen Ordnung vor dem ersten Zeichen der Kante (v, w) steht. (Dabei wird angenommen, dass $ ≤ c, ∀c ∈ Σ, wobei $ das Ende der Zeichenkette bezeichnet). Jetzt kann der Tiefendurchlaufalgorithmus anwendet werden. Die Reihenfolge, in der die Bl a¨ tter des Suffix Tree besucht werden, gibt die Reihenfolge der Eintr¨age in dem Suffix Array.

3.4

Direkte Konstruktion von Suffix Array

Eine direkte Konstruktion von Suffix Arrays erfolgt in O(n log n) Zeit. Dabei wird auf die Idee des Bucket-Sorts ¨ zuruckgegriffen. Im ersten Schritt wird das Array pos mit allen Suffixen absteigend nach deren L a¨ nge initialisiert. Dann werden die Zeichenketten nach dem ersten Zeichen sortiert, wobei eine Menge von Buckets entsteht. Jeder Bucket enth¨alt alle Suffixe, die mit dem selben Buchstaben anfangen.

Abbildung 3: Das Array pos nach der ersten Phase. Im zweiten Schritt muss nach dem zweiten Buchstaben sortiert werden, aber nur innerhalb der Buckets. Seien t = ti . . . tn $ und tj = tj . . . tn $ zwei Suffixen in einem Bucket. D.h. ti = tj und es muss jeweils nach dem zweiten Zeichen sortiert werden-ti+1 und tj+1 . Der Vergleich hat das selbe Ergebnis, wie der Vergleich von t i+1 = ti+1 . . . tn $ mit ti+1 = ti+1 . . . tn $ von der erste Phase des Algorithmus. Also werden in diesem Schritt in jedem Bucket die Suffixen ti so sortiert, wie ti+1 nach dem ersten Zeichen. Dabei wird das Array pos neu sortiert, wobei neue Buckets ¨ entstehen, in den je die ersten zwei Buchstaben der Suffixen ubereinstimmen. Im dritten Schritt wird gleichzeitig nach dem dritten und vierten Zeichen sortiert, d.h. es werden t i+2 ti+3 und tj+2 tj+3 verglichen. Der Vergleich wurde aber bereits implizit gemacht, es liefert das Ergebnis wie in Phase zwei, wo ti+2 = ti+2 . . . tn $ und tj+2 . . . tn $ sortiert wurden. Es werden nun also die Suffixen ti genau so sortiert, wie ti+2 nach den ersten zwei Buhstaben. Es wird analog weiter verfahren, in dem in jedem Schritt die Anzahl der verglichenen Symbolen sich verdoppelt. ¨ Es werden maximal log(n) Phasen durchgefuhrt. Am Ende besteht das Suffix Array aus genau n + 1 Buckets, der je einen Suffix enth¨alt. ¨ direkte Konstruktion O(n log n) Zeit. Insgesamt braucht der Algorithmus von Manber und Myers f ur i

3.5

Auffinden von Mustern im Suffix Array

¨ den Text t ist schon gegeben durch pos. Die gesuchte Teilzeichenkette sei q = Angenommen das Suffix Array fur q1 . . . q h . ¨ Wenn q in t enhalten ist, dann mussen alle Vorkommen von q in dem Array pos lexikographisch angeordnet sein. Da lexikographisch a¨ nlichen Suffixen nebeneinander im Array stehen, ist es sinnvoll bin a¨ re Suche zu verwenden. Bei

5

¨ dieser Art Suche werden O(log n) Vergleiche durchgef uhrt und jeder Vergleich muss in O(h) Positionen suchen. Also ¨ benotigt dieser Algorithmus O(h log n) Zeit. - Erster Speed-up Sei L die linke Grenze und R die rechte Grenze des aktuellen Suchintervalls. ¨ Dabei seien t = t1 . . . tn ∈ Σ und pos das zugehorige Suffix Array. Der l¨angste gemeinsame Pr¨afix (LGP engl. longest common prefix) von den Positionen i < j ∈ 0, . . . , n der Wert lcp(i, j) = k, wenn t A[i] . . . tA[i]+k−1 = tA[j] . . . tA[j]+k−1 und tA[i]+k < tA[j]+k . Sei nun l die L¨ange des LGP von q und spos[L] (Suffix gestartet aus der Position pos[L]), r die La¨ nge des LGP von q und spos[R] und mlr = min(l, r). Da die Eintr¨age von pos lexikographisch angeordnet sind, sind die ersten mlr ¨ alle i ∈ [L, R] gleich. Daher konnen ¨ ¨ Zeichen von spos[i] fur die bei dem Vergleich von q mit spos[M ] ubersprungen werden. So haben wir eine Beschleunigung erreicht, die in der Praxis die Zeitkomplexit a¨ t von O(h + log n) hat. Worst-case ist aber immer noch O(h log n). - Zweiter Speed-up ¨ ¨ ¨ ¨ ¨ Das Uberpr ufen eines Zeichens aus q wird redundant/uberfl ussig genannt, wenn dieses Zeichen schon uber¨ wurde. Man kann diese redundante Kontrollen zu maximal eine per Iteration der Bin a¨ re Suche reduziepruft ren, also zu O(log n). Das beschleunigt den Algorithmus zu O(h + log n).

3.6

Anwendung

¨ ¨ Suffix Arrays konnen die selben Aufgaben wie Suffix Trees erfullen, mit dem Unterschied, dass sie wesentlich weni¨ kleinere Alphabete geeignet. ger Platz verbrauchen. Diese Datenstruktur ist besonders f ur

Literatur [1] Suffix Trees in Computational Biology. (http://homepage.usask.ca/∼ctl271/857/suffix tree.shtml). [2] Wally Bitar. Introduction to Bioinformatics (http://www.msci.memphis.edu/∼giri/compbio/f00/Wally/Wally.html).

Generalized

Suffix

Trees.

[3] M. Crochemore and W. Rytter. Jewels of Stringology. World Scientific, 2002. [4] D. Gusfield. Algorithms on Strings,Trees, and Sequences. Cambridge University Press, 1997. [5] V. Heun. Algorithmen auf Sequenzen. Skriptum zur Vorlesung, 2004. [6] D. Huson. Algorithms in Bioinformatiks. Lecture, May 2005. [7] U. Manber and G.Myers. Suffix Arrays: a new method for on-line string searching. SIAM Journal on Computing, 1993.

6