Zaawansowane algorytmy i struktury danych/Wykład 2
<dont size="6">Zaawansowane algorytmy tekstowe II
W module tym zajmiemy się strukturami danych reprezentującymi zbiór wszystkich podsłów danego słowa ,zapisywany jako . Oznaczmy wszsytkie wystąpienia (początkowe pozycje) słowa w słowie przez . ( jest skrótem od ang. Occurrences.
Chcemy znaleźć taką reprezentację zbioru by można było łatwo odpowiedzieć na pytanie , (co jest równoważne ) jak również rozwiązywać inne problemytekstowe. Poza tym chcemy by rozmiar tej eprezentacji był liniowy, podczas gdy rozmiar może byćkwadratowy. Spośród wielu dobrych reprezentacji najbardziej znanymi są tablice sufiksowe (oznaczane przez) i drzewa sufiksowe.
Niech
, oraz niech
będzie specjalnym znakiemleksykograficznie mniejszym od każdego innego symbolu. Oznaczmy przez
sufiks tekstu x zaczynający się na pozycji i-tej. Niech
będzie pozycją od której zaczyna się k-tyleksykograficznie sufiks x. Sufiks zaczynający się na pozycji
-szej nie jest brany pod uwagę. Ciąg sufiksów posortowany leksykograficznie wygląda następująco:
\begin{figure}[hbt]\begin{center}\includegraphics[width=7cm]{teksty_fig20.eps} \caption{Tablicą sufiksową tekstu
jest ciąg
Wartości najdłuższego wspólnego prefiksu między kolejnymi słowami są przedstawione jakozacienione segmenty. Odpowiadają one tablicy
. }\end{center}\end{figure}
\noindentOznaczmy przez długść wspólnego prefisku -tego i następnego sufiksuw kolejności leksykograficznej.\myskip \noindent Tablica sufiksowa ma następująca miłą własność: Niech \begin{center},\\.\end{center}Wtedy jest przedziałem w tablicy sufiksowej od do .\myskip Drzewo sufiskowe jest drzewem, w którym każda ścieżka jest etykietowana kolejnymi symbolamipewnego sufiksu, oraz każdy sufiks jest obecny w drzewie. Gdy dwie ścieżki się {\em rozjeżdżają}tworzy się wierzchołek. Mówiąc bardziej formalnie każdej krawędzi jest przypisane jako etykieta pewnepodsłowo . Krawędzie wychodzące z tego samego węzła różnią się pierwszymi symbolami swoich etykiet,patrz rysunek. Etykiety są kodowane przedziałami w tekście , para liczb reprezentuje podsłowo Parser nie mógł rozpoznać (nieznana funkcja „\ldotsa”): {\displaystyle a_ia_{i+1}\ldotsa_j} , zobacz prawe drzewo na rysunku. Dzięki temu reprezentacja ma rozmiar . Wagą krawędzi jestdługość odpowiadającego jej słowa. \myskip\begin{figure}[bh]\begin{center}\includegraphics[width=15cm]{teksty_fig15.eps} \caption{Drzewo sufiksowe dla tekstu . Na ko"ncu jest dodany zank . Ko"ncowe węzły zawierająinformację gdzie zaczyna się sufiks, którym dochodzimy do danego węzła.}\end{center}\end{figure}\myskip Obie reprezentacje rozwiązują szybko problem string-matchingu, oraz mają rozmiar liniowy.
\noindent Niech z będzie wzorcem o długości m, a
słowem długośći n. Z reguły
.\subsection*{Szukanie podsłów}Pokażemy jak sprawdzać, czy
występuje w
.\begin{description}\item{Używając drzewa sufiskowego}, czas
}\mbox{ \ \\{\em Idziemy} od korzenia w dół czytając kolejnesymbole
, czasami posuwamy się po wewnętrznej etykiecie pewnej krawędzi. Zbiór wystąpie"n odpowiadazbiorowi liści w poddrzewie węzła do którego doszliśmy. Jeśli po drodze {\em utknęliśmy} i nie dało siędalej schodzić po drzewie to oznacza, że
.\item{Używając tablicy sufiksowej}, czas
}\mbox{ \ \\Możemy sprawdzić czy
jest prefiksem
-tego sufiksu w czasie
. Korzystając z tego wykonujemy rodzaj{\em binary search}, znajdujemy pierwszy sufiks, którego prefiksem jest z. Jeśli jest taki sufiks to Parser nie mógł rozpoznać (nieznana funkcja „\inSubwords”): {\displaystyle z \inSubwords(x)} . W przeciwym wypadku z nie jest podsłowem x. Podobnie znajdujemy ostatni sufiks. Zbiór wystąpie"nodpowiada przedziałowi w tablicy
między obliczonymi pierwszym i ostatnim sufiksem zaczynającym się odz.\end{description}\subsection*{Liczenie liczby podsłów}Pokażemy jak liczyć liczbę podsłów słowa
mając tablicę sufiksową lub drzewo sufiksowe. Ko"ncowymarker
nie traktujemy jako części słowa
. Liczba podsłów jest równa
. Jeśliwszsytkie symbole słowa są różne to Parser nie mógł rozpoznać (błąd składni): {\displaystyle |Subwords(x)|={\choose {n} 2}} .\begin{description}\item{Używając drzewa sufiskowego}, czas
}\mbox{ \ \\Sumujemy wagi krawędzi drzewa.\item{Używając tablicy sufiksowej}, czas
}\mbox{ \ \\Niech
będzie sumą elementówtablicy
. Liczbę podsłów obliczamy jako
\end{description} \noindent Pozostawiamy jako ćwiczenie uzasadnienie tego, że liczba podsłów jest poprawnie obliczona(korzystając z drzewa sufisowego lub z tablicy sufiksowej). \myskip Przykład.\ Dla przykładowego Parser nie mógł rozpoznać (nieznana funkcja „\babaabababba”): {\displaystyle x\ =\babaabababba} mamy
. Proponujemy to wyliczyć z tablicy sufiksowej i drzewa sufiskowego dla
, danego na rysunku. Suma elementów tablicy
wynosi 23. Mamy liczbę podsłów jako: \
\myskip\noindent Podobnie jak tablicę sufiksową możemy zdefiniować tablicę
odpowiadającą posortowanemuciągowi wszystkich cyklicznych przesunięć słowa
(rotacji
). \myskip Pozostawiamy jako ćwiczenieznalezienie liniowego algorytmu liczącego tablicę
, zakładając, że mamy liniowy algorytm liczeniatablicy sufiksowej. \myskip Dysgresja.\ Ciekawą klasą słów dla których tablice
sąszczególnie interesujące są słowa Fibonacciego
. W tym szczególnym przypadku załóżmy, że pozycjenumerujemy od zera. Dla każdego
tablica
jest postępem arytmetycznym (modulo długość słowa).Natomiast tablica
jest postępem arytmetycznym gdy
jest parzyste.\myskipSłowa Fibonacciego definiujemy następująco:\
\Na przykład:\
\ Oznaczmy przez
tablicę
dla słowa Fibonacciego
, wtedy:</math>SUF_4\ =\ [7\;2\;5\;0\;3\;6\;1\;4],\ \SUF_5\ =\ [10\;7\;2\;11\;8\;5\;0\;3\;12\;9\;6\;1\;4].
W celu znalezenia początkowych pozycji sufiksów w porządku leksykograficznym przechodzimy drzewo sufiksowemetodą DFS, zakładając, że dla każdego węła lista jego synów jest w kolejności leksykograficznej etykietkrawędzi prowadzących do synów. Wystarczy sprawdzać piewsze symbole tych etykiet. Załóżmy, że w liściach mamy początki sufiksów, które do nich prowadzą.Kolejność odwiedzania liści w naszym przejściu metodą DFS automatycznie generuje elementy tablicy sufiksowej.%%===================================================================================
Pokażemy konstruktywanie następujący istotny fakt: \vskip 0.1cm jeśli znamy tablicę sufiksową i tablicę to drzewo sufiksowe dla danego tekstu możemy {\em łatwo} skonstruować w czasie liniowym.\myskipPrzypuśćmy, że, , a więc:</math>sufiks_{i_1}< sufiks_{i_2}< sufiks_{i_3}< \ldots sufiks_{i_n}.
for to do\\\hspace*{1cm} wstaw nową ścieżkę o sumarycznej etykiecie do ; \myskip\end{minipage}\end{center} \begin{figure}[ht]\begin{center}\includegraphics[width=4.7cm]{teksty_fig16.eps}\caption{ Wstawianie kolejnego sufiksu do drzewa sufiskowego, przed włożeniem wszystkiekrawędzie{\em ścieżki roboczej} od do korzenia {są skierowane } w lewo. } \end{center}\end{figure} Opiszemy w jaki sposób wstawiamy kolejny sufiks do drzewa. Operacja ta jest zilustrowana na rysunku.Załóżmy, że w każdym węźle drzewa trzymamy długość tesktu, który ten węzeł reprezentuje (jako pełnaetykieta od korzenia do węzła). Niech będzie poprzednio wstawionym sufiksem, a ostatniopoprzednio utworzonym liściem. Wtedy wstawienie polega na znalezieniu maksymalnego wspólnego prefiksu tekstów , . Niech . Znajdujemy węzeł odpowiadający ścieżceod korzenia etykietowanej . Podstawowym {\em trikiem} jest to, że węzła szukamy nie od korzenia,ale od ostatnio utworzonego liścia . Jeśli takiego węzła nie ma (jest wewnątrz krawędzi) to gotworzymy. Następnie tworzymy nowy liść odpowiadający sufiksowi , oraz krawędź etykietowaną . Z tablicy odczytujemy długość . W celu obliczenia posuwamy się ścieżką od w górędrzewa, aż znajdziemy węzeł oddalony od korzenia o . Przechodząc drzewo posuwamy się po węzłachdrzewa, przeskakując potencjalnie długie teksty na krawędziach. \myskipKoszt operacji wstawienia jestproporcjonalny do sumy: jeden plus zmniejszenie głębokości nowego liścia w stosunku do starego. Suma tychzmniejsze"n jest liniowa. jest najdłuższym wspólnym prefiksem słów i. Kluczowe znaczenie w operacji ma znajomość wartości . Wiemy kiedy sięzatrzymać idąc do góry od węzła w kierunku korzenia. \myskipLokalnie wykonana praca w jednej iteracjijest zamortyzowana zmniejszeniem się głębokości aktualnego liścia w stosunku do porzedniego.\myskipHistoria algorytmu jest pokazana dla przykładowego tekstu na rysunkach. \begin{figure}[ht]\begin{center}\includegraphics[width=10cm]{teksty_fig17.eps}\caption{Pierwsze 6 iteracji algorytmu Drzewo-Sufiksowe dla tekstu . } \end{center}\end{figure}
\begin{figure}[htb]\begin{center}\includegraphics[width=14.4cm]{teksty_fig18.eps}\caption{Ostatnie 6 iteracji algorytmu Drzewo-Sufiksowe dla tekstu . } \end{center}\end{figure}
Niech b"dzie poycją w porządkuleksykograficznym. W naszym przykładowym słowie mamy: </math>rank\ =\ [8,\ 2,\ 7,\ 1,\ 3,\ 9,\ 4,\ 10,\ 5,\ 12,\11,\ 6]
for to do\\\hspace*{0.5cm} oblicz korzystając z faktu, że; \\\hspace*{0.7cm} koszt iteracji for to do\\\hspace*{0.5cm} := \myskip\end{minipage}\end{center} Pozostawimay jako ćwiczenie dowód tego, że . Jeśli to obliczamy sprawdzając symbol po symbolu (od lewej do prawej) zgodność pefiksów odpowiednich słów startującod pozycji . W ten sposób sumaryczny koszt jest liniowy. W każdej iteracji cofamy się o jeden, a potemidziemy {\em do przodu} (sprawdzając kolejne symbole). Jest to analiza typu {\em jeden krok do tyłu i kilka doprzodu}. Liczba iteracji jest liniowa, więc liczba kroków do tyłu też. Poniewaź odległość {\em do celu}jest liniowa, to suma kroków też jest liniowa. Opiszemy uproszczoną wersję algorytmu Karpa-Millera-Rosenberga (w skrócie algorytmu {\em KMR})rozwiązywania problemów tekstowych metodą {em słownika bazowego}. Ustalmy pewnie tekst długości .Załóżmy, że dodatkowym symbolem jest , leksykograficznie najmniejszy symbol. Przez -bazowysegment rozumiemy segment długości lub ko"nczący się na . Teoretyczniemożemy założyć, że po symbolu mamy bardzo dużo takich symboli na prawo i każde segment startujący w ma {\em dokładnie } długość . Słowanik podsłów bazowych} (w skrócie , od ang. {\em dictionary of basic factors) składa sięz tablic Parser nie mógł rozpoznać (nieznana funkcja „\textsl”): {\displaystyle \textsl{NAZWA}_0} ,\ Parser nie mógł rozpoznać (nieznana funkcja „\textsl”): {\displaystyle \textsl{NAZWA}_1} ,\ Parser nie mógł rozpoznać (nieznana funkcja „\textsl”): {\displaystyle \textsl{NAZWA}_2} ,\ldots Parser nie mógł rozpoznać (nieznana funkcja „\textsl”): {\displaystyle \textsl{NAZWA}_{\log n}} . Zakładamy, że Parser nie mógł rozpoznać (nieznana funkcja „\textsl”): {\displaystyle \textsl{NAZWA}_k[i]} jest pozycją słowa na posortowanej liście (bezpowtórze"n) wszystkich podsłów długości słowa . Jeśli długość {\em wystaje} poza koniec toprzyjmujemy że są tam (wirtualnie) same symbole . Poniżej przedsatwiamy przykład słownika podsłówbazowych . \vskip 0.5cm