]> mj.ucw.cz Git - ga.git/commitdiff
Finish.
authorMartin Mares <mj@ucw.cz>
Fri, 29 Dec 2006 00:20:25 +0000 (01:20 +0100)
committerMartin Mares <mj@ucw.cz>
Fri, 29 Dec 2006 00:20:25 +0000 (01:20 +0100)
9-suffix/9-suffix.tex

index 7045e3e672e93afd2bd3c7fefbd3c7516927b767..3841d687b8d813b22dc2484cc9ba9739bf6be887 100644 (file)
@@ -37,16 +37,17 @@ Podslova jsou pr
 Hrany si mù¾eme pøedstavit popsané písmeny, o~nì¾ prefix roz¹iøují, popisky hran na~cestì z~koøene do~vrcholu~$\alpha$ dají právì slovo~$\alpha$.
 
 \s{Definice:} {\I Komprimovaná trie ($\Sigma^+$-strom)} vznikne z trie nahrazením maximálních nevìtvících se cest hranami. Hrany
-jsou tentokrát popsané øetìzci místo jednotlivými písmeny, pøièem¾ popisky v¹ech hrany vycházející z~jednoho vrcholu se li¹í v~prvním
+jsou tentokrát popsané øetìzci místo jednotlivými písmeny, pøièem¾ popisky v¹ech hrany vycházejících z~jednoho vrcholu se li¹í v~prvním
 znaku. Vrcholùm \uv{uvnitø hran} (které padly za obìt kompresi) budeme øíkat {\I skryté vrcholy.}
 
+\medskip
 \tabskip=0pt plus 1fil
 \halign to\hsize{
 \hfil#\hfil&\hfil#\hfil&\hfil#\hfil\cr
 \epsfbox{trie.eps}&\epsfbox{trie-c.eps}&\epsfbox{trie-cd.eps}\cr
-Trie pre $\{\hbox{AULA, AUTO, AUTOBUS, BUS}\}$ & \dots komprimovaná & \dots odolarovaná\cr
+Trie pro $\{\hbox{AULA, AUTO, AUTOBUS, BUS}\}$ & \dots komprimovaná & \dots odolarovaná\cr
 }
-\smallskip
+\medskip
 
 \s{Definice:} {\I Suffixový strom (ST)} pro slovo $\sigma\in\Sigma^*$ je komprimovaná trie pro $X=\{\alpha: \hbox{$\alpha$ je suffixem $\sigma$}\}$.
 
@@ -61,7 +62,7 @@ s~t
 jinde nevyskytuje. Suffixy slova $\sigma\$$ odpovídají suffixùm slova~$\sigma$ (kdy¾ pomineme
 prázdný suffix) a ¾ádný z~nich nemù¾e být vnoøený.
 
-\figure{st-barbara.eps}{Sufixový strom pre slovo BARBARA}{0pt}
+\figure{st-barbara.eps}{Suffixový strom pro slovo BARBARA}{0pt}
 
 \s{Lemma:} Suffixový strom pro slovo $\sigma$ délky $n$ je reprezentovatelný v~prostoru $\O(n)$.
 
@@ -108,7 +109,7 @@ list
 ve~stromu, tak¾e staèí pro strom vybudovat datovou strukturu pro spoleèné pøedchùdce
 a s~její pomocí doká¾eme jeden støed prozkoumat v~konstantním èase.
 
-\:{\I Burrows-Wheelerova Transformace} -- jejím základem je lexikografické setøidìní v¹ech
+\:{\I Burrows-Wheelerova Transformace} -- jejím základem je lexikografické setøídìní v¹ech
 rotací slova~$\sigma$, co¾ zvládneme sestrojením ST pro slovo~$\sigma\sigma$, jeho
 uøíznutím v~písmenkové hloubce~$\vert\sigma\vert$ a následným vypsáním listù v~poøadí dle~DFS.
 \endlist
@@ -118,15 +119,21 @@ u
 \>V~nìkterých pøípadech se hodí místo suffixového stromu pou¾ívat kompaktnìj¹í datové struktury.
 
 \s{Notace:} Pro slovo $\sigma$ bude $\sigma[i:j]$ znaèit podslovo slo¾ené z~$i$-tého a¾ $j$-tého
-znaku slova~$\sigma$ (znaky èíslujeme od~$1$). Navíc $\sigma[i:{}]$ bude suffix od~$i$ do~konce
-a $\sigma[{}:j]$ prefix od~zaèátku do~$j$. Prázdný suffix mù¾eme znaèit jako $\sigma[\vert\sigma\vert+1:{}].$
+znaku slova~$\sigma$ (znaky èíslujeme od~$1$). Libovolnou z~mezí mù¾eme vynechat, tak¾e
+$\sigma[i:{}]$ bude suffix od~$i$ do~konce a $\sigma[{}:j]$ prefix od~zaèátku do~$j$.
+Pokud $j<i$, definujeme $\sigma[i:j]$ jako prázdné slovo, tak¾e prázdný suffix mù¾eme
+napøíklad zapsat jako $\sigma[\vert\sigma\vert+1:{}].$
+
+${\rm LCP}(\alpha,\beta)$ bude znaèit délku nejdel¹ího spoleèného prefixu slov $\alpha$ a $\beta$,
+èili nejvìt¹í $i$ takové, ¾e $\alpha[{}:i]=\beta[{}:i]$.
 
 \s{Definice:} {\I Suffix Array} $A_\sigma$ pro slovo $\sigma$ délky~$n$ je posloupnost v¹ech suffixù
 slova~$\sigma$ v~lexikografickém poøadí. Mù¾eme ho reprezentovat napøíklad jako permutaci $A$ èísel
 $1,\ldots,n+1$, pro ní¾ $\sigma[A[1]:{}] < \sigma[A[2]:{}] < \ldots < \sigma[A[n+1]:]$.
 
 \s{Definice:} {\I Longest Common Prefix Array} $L_\sigma$ pro slovo $\sigma$ je posloupnost,
-v~ní¾ $L_\sigma[i]$ udává délku nejdel¹ího spoleèného prefixu slov $A_\sigma[i]$ a $A_\sigma[i+1]$.
+v~ní¾ $L_\sigma[i]$ udává délku nejdel¹ího spoleèného prefixu slov $A_\sigma[i]$ a $A_\sigma[i+1]$,
+èili $L_\sigma[i]={\rm LCP}(A_\sigma[i],A_\sigma[i+1])$.
 
 \s{Vìta:} Suffixový strom pro slovo $\sigma$ s~dolarem je lineárnì ekvivalentní s~dvojicí $(A_\sigma,L_\sigma)$.
 [Jinými slovy, kdy¾ máme jedno, mu¾eme z~toho v~lineárním èase spoèítat druhé a naopak.]
@@ -146,7 +153,7 @@ v
 
 \algo
 \:Redukujeme abecedu na~$1\ldots n$: ve~vstupním slovu je nejvý¹e $n$ rùzných znakù,
-tak¾e je staèí setøidit a pøeèíslovat.
+tak¾e je staèí setøídit a pøeèíslovat.
 
 \:Definujeme slova $\sigma_0$, $\sigma_1$, $\sigma_2$ následovnì:
 $$\eqalign{
@@ -162,14 +169,14 @@ si m
 \:Z~$A_{01}$ a $L_{01}$ vydìlíme $A_0=A_{\sigma_0}$, $A_1$, $L_0$ a $L_1$ a spoèítáme permutace inverzní k~$A_0$ a $A_1$.
 
 \:Dopoèítáme $A_2$: Jeliko¾ $\sigma_2[i:{}] = \sigma[3i+2:{}] = \sigma[3i+2]\sigma[3i+3:{}] = \sigma[3i+2]\sigma_0[i+1:{}]$
-a v¹echna $\sigma_0[i:{}]$ u¾ máme setøidìná, mù¾eme v¹echna $\sigma_2[i:{}]$ setøídit dvìma prùchody pøíhrádkového tøídìní.
+a v¹echna $\sigma_0[i:{}]$ u¾ máme setøídìná, mù¾eme v¹echna $\sigma_2[i:{}]$ setøídit dvìma prùchody pøíhrádkového tøídìní.
 
 \:Dopoèítáme $L_2$: Stejným trikem jako $A_2$ -- pokud jsou první písmena rùzná, je spoleèný prefix prázdný, jinak
-má délku $1+{\rm LCP}(\sigma_0[i+1:{}],\sigma_0[j+1:{}]) = \min_{i+1\le k< j+1} L_0[k]$. To zvládneme v~konstantním
-èase na~operaci pomoci datové struktuy pro intervalová minima.
-\todo{Ta je a¾ v~následující kapitole, co¾ není pìkné.}
+má délku $1+{\rm LCP}(\sigma_0[i+1:{}],\sigma_0[j+1:{}]) = \min_{i+1\le k< j+1} L_0[k]$. Minimum zvládneme pro ka¾dou
+dvojici $i,j$ spoèítat v~konstantním èase pomocí datové struktury pro intervalová minima.
+\todo{Ta je a¾ v~následující kapitole.}
 
-\:$A_0,A_1,A_2\buildrel merge\over\longrightarrow A$ -- sléváme tøi setøidìné posloupnosti,
+\:$A_0,A_1,A_2\buildrel merge\over\longrightarrow A$ -- sléváme tøi setøídìné posloupnosti,
 tak¾e staèí umìt prvky libovolných dvou posloupností v~konstantním èase porovnat:
 $$\eqalign{
 \sigma_0[i:{}] < \sigma_1[j:{}] &\equiv A_{01}^{-1}[i] < A_{01}^{-1}[\vert\sigma_0\vert+j]\cr
@@ -178,18 +185,18 @@ $$\eqalign{
 \sigma_1[j:{}]<\sigma_2[k:{}] &\equiv \sigma[3j+1]\,\sigma[3j+2]\,\sigma_0[j+1:{}] < \sigma[3k+2]\,\sigma[3k+3]\,\sigma_1[k+1:{}]
 }$$
 
-\:Dopoèítame $L$ -- pokud sousedí suffix ze~$\sigma_{0,1}$ se suffixem ze~$\sigma{0,1}$,
+\:Dopoèítame $L$ -- pokud sousedí suffix ze~$\sigma_{0,1}$ se suffixem ze~$\sigma_{0,1}$,
 vyèteme výsledek pøímo z~$L_{01}$. Pokud sousedí $\sigma_2$ se $\sigma_2$, staèí pou¾ít
 u¾ spoèítané $L_2$. Pokud sousedí $\sigma_{0,1}$ se $\sigma_2$, odebereme první jeden
 nebo dva znaky, ty porovnáme samostatnì a v~pøípadì shody zbude suffix ze~$\sigma_0$
 a suffix ze~$\sigma_1$ (stejnì jako pøi slévání) a pro ty doká¾eme $L$ dopoèítat
-pomocí struktury pro intervalová minima v~$L_01$.
+pomocí struktury pro intervalová minima v~$L_{01}$.
 
 \endalgo
 
 \s{Analýza èasové slo¾itosti:} Tøídìní v~prvním volání trvá ${\rm Sort}(n,\Sigma)$, ve~v¹ech
 ostatních voláních je lineární (trojice èísel velikosti $\O(n)$ mù¾eme tøídit tøíprùchodovým
-pøíhrádkovým tøídìním s~$\O(n)$ pøíhrádkami). Dostáváme tedy:
+pøíhrádkovým tøídìním s~$\O(n)$ pøíhrádkami). Z~toho dostáváme:
 $$T(n) = T(2/3\cdot n) + \O(n),~\hbox{a tedy}~T(n)=\O(n).$$
 \qed
 
@@ -203,16 +210,20 @@ Pro slovo~$\sigma$ tedy dok
 \s{Pozorování:} Kdy¾ slovo~$\sigma$ roz¹íøíme na~$\sigma a$, ST se zmìní následovnì:
 
 \numlist\ndotted
-\:Pokud $\beta$ byl nevnoøený suffix $\sigma$, je i $\beta a$ nevnoøený suffix -- listy
-zùstanou listy, pouze jim potøebujeme prodlou¾it nálepky. Pomu¾eme si snadno: zavedeme
-{\I otevøené hrany,} jejich¾ nálepka je \uv{od~pozice~$i$ do konce}. Listy se tedy
+\:Pokud $\beta$ byl nevnoøený suffix $\sigma$, je i $\beta a$ nevnoøený suffix. Z~toho víme, ¾e listy
+zùstanou listy, pouze jim potøebujeme prodlou¾it nálepky. Pomù¾eme si snadno: zavedeme
+{\I otevøené hrany,} jejich¾ nálepka je \uv{od~pozice~$i$ do konce}. Listy se tak
 o~sebe postarají samy.
-\:Pokud $\beta$ bylo vìtvící slovo, zùstane nadále vìtvící -- vnitøní vrcholy tedy zùstanou.
-\:Pokud $\beta$ byl vnoøený suffix (tj. vnitøní èi skrytý vrchol), je $\beta a$ buïto
-také vnoøený (a postará se o~sebe sám), nebo se vùbec nevyskytuje v~$\sigma$ a musíme
-pro~nìj zalo¾it novou odboèku a nový list s~otevøenou hranou.
+\:Pokud $\beta$ bylo vìtvící slovo, zùstane nadále vìtvící -- tedy vnitøní vrcholy ve~stromu zùstanou.
+\:Pokud $\beta$ byl vnoøený suffix (tj. vnitøní èi skrytý vrchol), pak se $\beta a$ buïto
+vyskytuje v~$\sigma$ a tím pádem je to vnoøený suffix nového slova a strom není nutné
+upravovat, nebo se v~$\sigma$ nevyskytuje a tehdy pro nìj musíme zalo¾it novou odboèku
+a nový list s~otevøenou hranou.
 \endlist
 
+Víme tedy, co v¹echno musí algoritmus ve~stromu pøí roz¹íøení slova upravit, zbývá
+vyøe¹it, jak to udìlat efektivnì. K~tomu se hodí pár definic a lemmat:
+
 \s{Definice:} {\I Aktivní suffix} $\alpha(\sigma)$ øíkáme nejdel¹ímu vnoøenému suffixu slova~$\sigma$.
 
 \s{Lemma:} Suffix $\beta$ slova $\sigma$ je vnoøený $\Leftrightarrow$ $\vert\beta\vert \le \vert\alpha(\sigma)\vert.$
@@ -222,7 +233,7 @@ pro~n
 \s{Lemma:} Pro ka¾dé $\sigma$, $a$ platí: $\alpha(\sigma a)$ je suffixem $\alpha(\sigma)a.$
 
 \s{Dùkaz:} $\alpha(\sigma a)$ i $\alpha(\sigma)a$ jsou suffixy slova $\sigma a$, a~proto staèí porovnat jejich délky.
-Slovo $\beta := \hbox{$\alpha(\sigma a)$ bez koncového~$a$}$ je vnoøený suffix v~$\sigma$, tak¾e
+Slovo $\beta := \hbox{\uv{$\alpha(\sigma a)$ bez koncového~$a$}}$ je vnoøeným suffixem v~$\sigma$, tak¾e
 $\vert\beta\vert \le \vert\alpha(\sigma)\vert$, a~tedy také $\vert\alpha(\sigma a)\vert = \vert\beta a\vert \le \vert\alpha(\sigma)a\vert$.
 \qed
 
@@ -239,49 +250,75 @@ mus
 stále vnoøený suffix. Pokud ano, nic se nemìní, pokud ne, pøidám vnitøní vrchol, $\alpha$ zkrátím
 zleva o~znak a testuji dál.
 
-\s{Èasová slo¾itost:} Úprav stromu provedu $\O(1)$ amortizovanì (ka¾dá úprava $\alpha$ zkrátí,
-ka¾dé pøidání znaku ho~prodlou¾í o~1, tak¾e v¹ech zkrácení je $\O(\vert\sigma\vert)$). Staèí
-tedy ukázat, jak provést úpravu v~(amortizovanì) konstantním èase.
+\s{Èasová slo¾itost:} Úprav stromu provedu $\O(1)$ amortizovanì (ka¾dá úprava slovo $\alpha$ zkrátí,
+ka¾dé pøidání znaku ho~prodlou¾í o~znak, tak¾e v¹ech zkrácení je $\O(\vert\sigma\vert)$). Staèí
+tedy ukázat, jak provést úpravu v~(amortizovanì) konstantním èase, k~èemu¾ se nám bude hodit:
+
+\s{Definice:} {\I Referenèní pár} je dvojice $(\pi,\tau)$, v~ní¾ $\pi$ je vrchol
+stromu a $\tau$ libovolné slovo. Tento pár popisuje slovo $\pi\tau$. Referenèní
+pár je {\I kanonický,} pokud neexistuje hrana vedoucí z~vrcholu $\pi$ s~nálepkou,
+která by byla prefixem slova~$\tau$.
 
-\todo{Zbytek dosud nezrevidován.}
+\s{Pozorování:} Ke~ka¾dému slovu existuje právì jeden kanonický referenèní pár,
+který ho popisuje. V¹imnìte si, ¾e je to ze~v¹ech referenèních párù pro toto slovo
+ten s~nejdel¹ím~$\alpha$ (nejhlub¹ím vrcholem).
 
-$\alpha(\sigma)$ reprezentuji jako kanonický (neexistuje jiný referenèní pár s krat¹ím $\alpha$) referenèní pár $(v, \alpha)$ kde $v$ je vrchol $ST$ a $\alpha$ ke cesta kudy dál.
+\s{Definice:} Zpìtná hrana $\<back>[\pi]$ vede z~vrcholu $\pi$ do~vrcholu,
+který je ze~v¹ech vrcholù nejdel¹ím vlastním suffixem slova~$\pi$.
 
-\s{Definice: $back[v]$} je nejdel¹í vlastní suffix $v$, ke kterému existuje vrchol.
+\s{Pozorování:} Zpìtné hrany jsme sice zavedli stejnì obecnì, jako se to dìlá
+pøi konstrukci vyhledávacích automatù podle Aha a McCorasickové, ale v~na¹em
+pøípadì se \<back> pro vnitøní vrcholy chová daleko jednodu¹eji (a~na ¾ádné
+jiné ho potøebovat nebudeme): pokud je $\pi$ vnitøní vrchol, musí to být
+vìtvící podslovo, a~tím pádem ka¾dé jeho zkrácení zleva musí být také vìtvící
+podslovo. Tedy $\<back>(\pi)$ dá~$\pi$ bez prvního znaku, co¾ se nám
+bude hodit pøi zkracování suffixù.
+
+\s{Algoritmus podrobnìji:} (Doplnili jsme detaily do~pøedchozího algoritmu.)
 
 \algo
-\:Vstup: $\sigma, a, (v, \alpha)$
-
-// 1. Zalo¾ení listù/Podrozdìlení hran
-\:if $\alpha = \varepsilon$:
-\::if $\exists (v, a* )$
-\:::konec
-\::else:
-\:::zalo¾ím list
-\:else if $\alpha \ne \varepsilon$:
-\::if $\exists (v, \alpha a*)$:
-\:::konec
-\::else:
-\:::podrozdìlím hranu na které le¾í $\alpha$ // za $\alpha$ vlo¾ím odboèku na $a$, kam dám list a pokraèuju
-
-// 2. Pøechod na dal¹í vrchol
-\:zkrátim $\alpha$ zleva o znak
-\:if $v = \varepsilon$:
-\::pøejdu do $( \varepsilon, \alpha bez 1. znaku)$
-\:else:
-\::pøejdu do $( back[v], \alpha )$
-
-// 3.
-\:kanonikalizuji // "jdu z $v$ pøes alpha do co nejdal"
+\:Vstup: $\alpha=\alpha(\sigma)$ reprezentovaný jako kanonický referenèní pár $(\pi,\tau)$, $T$ suffixový strom pro~$\sigma$ a jeho funkce \<back>, nový znak~$a$.
+\:Zjistíme, jestli $\alpha a$ je pøitomen ve~stromu:
+\::Pokud $\tau=\varepsilon$: ($\alpha=\pi$ je vnitøní vrchol)
+\:::Vede-li z~vrcholu $\pi$ hrana s~nálepkou zaèínající znakem $a$, pak je pøítomen.
+\:::Nevede-li, není pøítomen, a~tak pøidáme novou otevøenou hranu vedoucí do~nového listu.
+\::Pokud $\tau\ne\varepsilon$: ($\alpha$ je skrytý vrchol)
+\:::Najdeme hranu, po~ní¾ z~$\pi$ pokraèuje slovo $\tau$ (která to je, poznáme podle prvního znaku slova~$\tau$).
+\:::Pokud v~popisce této hrany po~$\tau$ následuje znak~$a$, pak je $\alpha a$ pøítomen.
+\:::Pokud nenásleduje, tak nebyl pøítomen, èili tuto hranu rozdìlíme: pøidáme na~ní nový vnitøní vrchol,
+    do~nìj¾ povede hrana s~popiskou~$\tau$ a z~nìj zbytek pùvodní hrany a otevøená hrana do~nového listu.
+\:Pokud $\alpha a$ byl pøítomen, tak $\alpha$ zkrátíme a test opakujeme:
+\::Je-li $\pi\ne\varepsilon$, nastavíme $\pi := \<back>(\pi)$. V~opaèném pøípadì (jsme v~koøeni) zkrátíme $\tau$ o~znak zleva.
+\::Pár $(\pi,\tau)$ u¾ popisuje zkrácené slovo, ale nemusí být kanonický, tak¾e to je¹tì napravíme:
+\:::Dokud existuje hrana vedoucí z~$\pi$, její¾ popiska je prefixem slova $\tau$, tak se
+    po~této hranì posuneme, èili prodlou¾íme $\pi$ o~tuto popisku a zkrátíme o~ni~$\tau$.
+\::Zpìt na~krok 2.
+\:Pokud $\alpha a$ u¾ je pøítomen, zbývá pøidat $a$ k~$\alpha$ a zastavit se:
+\::$\tau := \tau a$.
+\::Kanonikalizace stejnì jako v~bodech 12--13.
+\:Výstup: $\alpha=\alpha(\sigma a)$ coby kanonický referenèní pár $(\pi,\tau)$, $T$ suffixový strom pro~$\sigma a$
+  a jeho funkce \<back>.
 \endalgo
 
-
 \s{Èasová slo¾itost:}
-\numlist\ndotted
-\:Zalo¾ení listu/Podrozdìlení hrany -- $O(1)$
-\:Pøechod na dal¹í vrchol -- $O(1)$ za pøedpokladu existence $back(v)$
-\:Kanonikalizace -- amortizovanì za $O(1)$
-\:Update $back[v]$ -- jen pro vnitøní vrcholy, které vznikly v 1. podrozdìlením hrany. Ta hrana vede do vrcholu, který nav¹tíví pøí¹tí update v kroku 2. a buï tam ten vrchol je, nebo ho v tom kroku zakláda, tedy -- $O(1)$.
-\endlist
+
+Kanonikalizace pracuje v~amortizovanì konstantním èase, proto¾e ka¾dá její iterace
+zkrátí~$\tau$ a za~celou dobu bìhu algoritmu se~$\tau$ prodlou¾í jen jednou, a~to o~jeden znak.
+
+Prùchodù hlavním cyklem je, jak u¾ víme, amortizovanì konstantní poèet a ka¾dý prùchod
+zvládneme v~konstantním èase.
+
+Je¹tì jsme ale zapomnìli nastavovat novým vrcholùm jejich \<back>. To potøebujeme
+jen pro vnitøní vrcholy (na~zpìtné hrany z~listù se algoritmus nikdy neodkazuje)
+a v¹imneme si, ¾e pokud jsme zalo¾ili vrchol, odpovídá tento vrchol v¾dy souèasnému~$\alpha$
+a zpìtná hrana z~nìj povede do~zkrácení slova~$\alpha$ o~znak zleva, co¾ je
+pøesnì vrchol, který zalo¾íme (nebo zjistíme, ¾e u¾ existuje) v~pøí¹tí iteraci
+hlavního cyklu. V~dal¹í iteraci urèitì je¹tì nebudeme tuto hranu potøebovat,
+proto¾e $\pi$ v¾dy jen zkracujeme, a~tak mù¾eme vznik zpìtné hrany o~iteraci
+zpozdit a zvládnout to tak také v~èase $\O(1)$.
+
+Celkovì je tedy èasová slo¾itost inkrementálního udr¾ování suffixového
+stromu amortizovanì konstantní.
+\qed
 
 \bye