]> mj.ucw.cz Git - ga.git/commitdiff
Bug fixes.
authorMartin Mares <mj@ucw.cz>
Sat, 30 Dec 2006 22:28:53 +0000 (23:28 +0100)
committerMartin Mares <mj@ucw.cz>
Sat, 30 Dec 2006 22:28:53 +0000 (23:28 +0100)
9-suffix/9-suffix.tex

index 3841d687b8d813b22dc2484cc9ba9739bf6be887..b3c49b1195e5ab6bc13f603ed35d8f309e2e3e9d 100644 (file)
@@ -27,18 +27,18 @@ $\alpha$ je {\I vlastn
 \s{Pozorování:} Prázdné slovo je prefixem, suffixem i podslovem ka¾dého slova vèetnì sebe sama.
 Podslova jsou právì prefixy suffixù a také suffixy prefixù.
 
-\s{Definice:} {\I Trie ($\Sigma$-strom)} pro koneènou $X\subset\Sigma^*$ je orientovaný graf $G=(V,E)$, kde:
+\s{Definice:} {\I Trie ($\Sigma$-strom)} pro koneènou mno¾inu slov $X\subset\Sigma^*$ je orientovaný graf $G=(V,E)$, kde:
 \itemize\relax
 \:$V = \{\alpha: \alpha\hbox{ je prefixem nìjakého $\beta\in X$} \},$
 \:$(\alpha,\beta)\in E \equiv \exists x\in\Sigma: \beta=\alpha x$.
 \endlist
 
-\s{Pozorování:} Trie je strom s koøenem $\varepsilon$. Jeho listy jsou slova z $X$, která nejsou vlastním prefixem jiných slov z~$X$.
-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{Pozorování:} Trie je strom s koøenem $\varepsilon$. Jeho listy jsou slova z $X$, která nejsou vlastními prefixemy jiných slov z~$X$.
+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$ dávají 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í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.}
+jsou tentokrát popsané øetìzci místo jednotlivými písmeny, pøièem¾ popisky v¹ech hran vycházejících z~jednoho vrcholu se li¹í v~prvním
+znaku. Vrcholùm \uv{uvnitø hran} (které padly za obì» kompresi) budeme øíkat {\I skryté vrcholy.}
 
 \medskip
 \tabskip=0pt plus 1fil
@@ -59,8 +59,8 @@ pro n
 
 Nìkdy mù¾e být nepraktické, ¾e nìkteré suffixy neodpovídají listùm (proto¾e jsou vnoøené), ale
 s~tím se mù¾eme snadno vypoøádat: pøidáme na~konec slova~$\sigma$ nìjaký znak~$\$$, který se nikde
-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ý.
+jinde nevyskytuje. Neprázdné suffixy slova $\sigma\$$ odpovídají suffixùm slova~$\sigma$
+a ¾ádný z~nich nemù¾e být vnoøený. Takový suffixový strom budeme znaèit ST\$.
 
 \figure{st-barbara.eps}{Suffixový strom pro slovo BARBARA}{0pt}
 
@@ -80,14 +80,14 @@ po
 
 \numlist\ndotted
 \:{\I Inverzní vyhledávání} (tj. pøedzpracujeme si v~lineárním èase text a pak umíme pro libovolné
-slovo~$\alpha$ v~èase $\O(\vert\alpha\vert)$ rozhodnout, zda se v~textu vyskytuje.\foot{Èili pøesný
+slovo~$\alpha$ v~èase $\O(\vert\alpha\vert)$ rozhodnout, zda se v~textu vyskytuje)\foot{Èili pøesný
 opak toho, co~umí vyhledávací automat -- ten si pøedzpracovává dotaz.} -- staèí sestrojit~ST
 a pak jej procházet od~koøene. Také umíme najít v¹echny výskyty (odpovídají suffixùm, které mají
-jako prefix hledané slovo, tak¾e staèí vytvoøit ST s~dolarem a vypsat v¹echny listy pod
+jako prefix hledané slovo, tak¾e staèí vytvoøit ST\$ a vypsat v¹echny listy pod
 nalezeným vrcholem) nebo pøímo vrátit jejich poèet (pøedpoèítáme si pomocí DFS pro ka¾dý vrchol,
 kolik pod ním le¾í listù).
 
-\:{\I Nejdel¹í opakující se podslovo} -- takové podslovo je nutnì vìtvící, tak¾e staèí
+\:{\I Nejdel¹í opakující se podslovo} -- takové podslovo je v~ST\$ nutnì vìtvící, tak¾e staèí
 najít vnitøní vrchol s~nejvìt¹í {\I písmenkovou hloubkou} (tj. hloubkou mìøenou ve~znacích
 místo ve~hranách).
 
@@ -96,12 +96,12 @@ kolik p
 
 \:{\I Nejdel¹í spoleèné podslovo} slov~$\alpha$ a $\beta$ -- postavíme ST pro slovo $\alpha\$_1\beta\$_2$,
 jeho listy odpovídají suffixùm slov $\alpha$ a $\beta$. Tak¾e staèí pomocí DFS najít nejhlub¹í vnitøní
-vrchol, pod kterým se vyskytují listy pro~$\alpha$ i $\beta$. Podobnì mù¾eme sestrojit ST pro libovolnou
+vrchol, pod kterým se vyskytují listy pro~$\alpha$ i $\beta$. Podobnì mù¾eme sestrojit ST\$ pro libovolnou
 mno¾inu slov.\foot{Jen si musíme dát pozor, abychom si moc nezvìt¹ili abecedu, ale to bude jasné,
 a¾ pøedvedeme konkrétní konstrukce.}
 
 \:{\I Nejdel¹í palindromické podslovo} (tj. takové $\beta\subset\alpha$, pro nì¾ je $\beta_R=\beta$)
--- postavíme spoleèný ST pro slova $\alpha$ a $\alpha_R$. Postupnì procházíme pøes v¹echny mo¾né støedy
+-- postavíme spoleèný ST\$ pro slova $\alpha$ a $\alpha_R$. Postupnì procházíme pøes v¹echny mo¾né støedy
 palindromického podslova a v¹imneme si, ¾e takové slovo je pro ka¾dý støed nejdel¹ím spoleèným
 prefixem podslova od~tohoto bodu do~konce a podslova od~tohoto bodu (pozpátku) k~zaèátku,
 èili nìjakého suffixu $\alpha$ a nìjakého suffixu $\alpha_R$. Tyto suffixy ov¹em odpovídají
@@ -119,24 +119,23 @@ 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$). Libovolnou z~mezí mù¾eme vynechat, tak¾e
+znaku slova~$\sigma$ (znaky èíslujeme od~$1$). Libovolnou z~mezí mù¾eme vynechat, proto
 $\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]$.
+èili nejvìt¹í $i\le \vert\alpha\vert,\vert\beta\vert$ 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]$,
-èili $L_\sigma[i]={\rm LCP}(A_\sigma[i],A_\sigma[i+1])$.
+v~ní¾ $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.]
+\s{Vìta:} Suffixový strom s~dolarem pro slovo $\sigma$ je lineárnì ekvivalentní s~dvojicí $(A_\sigma,L_\sigma)$.
+[Jinými slovy, kdy¾ máme jedno, mù¾eme z~toho v~lineárním èase spoèítat druhé a naopak.]
 
 \s{Dùkaz:} Kdy¾ projdeme ST($\sigma$) do hloubky, poøadí listù odpovídá $A_\sigma$ a písmenkové hloubky vnitøních
 vrcholù v~inorderu odpovídají $L_\sigma$. Naopak ST($\sigma$) získáme tak, ¾e sestrojíme kartézský strom
@@ -162,17 +161,17 @@ $$\eqalign{
 \sigma_2[i] &:= \left<\sigma[3i+2],\sigma[3i+3],\sigma[3i+4]\right>\cr
 }$$
 Slova $\sigma_k$ jsou slova délky $\approx n/3$ nad~abecedou velikosti $n^3$. Dovolíme
-si mírnì zneu¾ívat notaci a znaèit $\sigma_k$ i jejich pøepis do~abecedy pùvodní.
+si mírnì zneu¾ívat notaci a pou¾ívat symbol $\sigma_k$ i jejich pøepis do~abecedy pùvodní.
 
-\:Zavoláme se rekurzivnì na slovo $\sigma_0\sigma_1$, èím¾ získáme $A_{01}$ a $L_{01}$.
+\:Zavoláme algoritmus rekurzivnì na slovo $\sigma_0\sigma_1$, èím¾ získáme $A_{01}$ a $L_{01}$.
 
 \: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øídì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øihrá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]$. Minimum zvládneme pro ka¾dou
+má délku $1+{\rm LCP}(\sigma_0[i+1:{}],\sigma_0[j+1:{}]) = 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.}
 
@@ -185,7 +184,7 @@ $$\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èítáme $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$
@@ -196,7 +195,7 @@ pomoc
 
 \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). Z~toho dostáváme:
+pøihrádkovým tøídìním s~$\O(n)$ pøihrádkami). Z~toho dostáváme:
 $$T(n) = T(2/3\cdot n) + \O(n),~\hbox{a tedy}~T(n)=\O(n).$$
 \qed
 
@@ -207,10 +206,14 @@ pro pr
 slova. To zvládne v~èase $\O(1)$ amortizovanì na~pøidání jednoho znaku.
 Pro slovo~$\sigma$ tedy doká¾e sestrojit ST v~èase $\O(\vert\sigma\vert)$.
 
+Budeme pøedpokládat, ¾e hrany vedoucí z~jednoho vrcholu je mo¾né indexovat jejich
+prvními písmeny -- to bezpeènì platí, pokud je abeceda pevná; není-li, mù¾eme
+si pomoci hashováním.
+
 \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. Z~toho víme, ¾e listy
+\:Pokud $\beta$ byl nevnoøený suffix slova~$\sigma$, je i $\beta a$ nevnoøený suffix~$\sigma a$. 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.
@@ -237,8 +240,8 @@ Slovo $\beta := \hbox{\uv{$\alpha(\sigma a)$ bez koncov
 $\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
 
-\s{Definice:} Suffix $\beta a$ je {\I zralý} (musíme pro~nìj pøi pøidávání znaku~$a$ k~aktuálnímu
-slovu~$\sigma$ zakládat nový vrchol) $\equiv$ $\beta$ je vnoøený suffix~$\sigma$, ale $\beta a$ není podslovem~$\sigma$.
+\s{Definice:} Suffix $\beta a$ je {\I zralý} $\equiv$ $\beta$ je vnoøený suffix~$\sigma$, ale $\beta a$ není podslovem~$\sigma$
+(tedy musíme pro~nìj pøi pøidávání znaku~$a$ k~aktuálnímu slovu~$\sigma$ zakládat nový vrchol).
 
 \s{Lemma:} Suffix $\beta$ je zralý $\Leftrightarrow$ $\vert\alpha(\sigma)a\vert \ge \vert\beta a\vert > \vert\alpha(\sigma a)\vert$.
 
@@ -246,11 +249,11 @@ slovu~$\sigma$ zakl
 musí také nebýt vnoøeným suffixem $\sigma a$, èemu¾ odpovídá druhá nerovnost.
 \qed
 
-\s{Algoritmus:} Udr¾uji si $\alpha=\alpha(\sigma)$ a pøi pøidání znaku $a$ zkontroluji, zda $\alpha a$ je
+\s{Idea Algoritmu:} Udr¾uji si $\alpha=\alpha(\sigma)$ a pøi pøidání znaku $a$ zkontroluji, zda $\alpha a$ je
 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 slovo $\alpha$ zkrátí,
+\s{Analýza:} Ú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:
 
@@ -261,7 +264,7 @@ kter
 
 \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).
+ten s~nejdel¹ím~$\pi$ (nejhlub¹ím vrcholem).
 
 \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$.
@@ -278,14 +281,14 @@ bude hodit p
 
 \algo
 \: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:
+\:Zjistíme, jestli $\alpha a$ je pøítomen ve~stromu, a pøípadnì ho zalo¾íme:
 \::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.
+\:::Nevede-li, není pøítomen, a~tak pøidáme novou otevøenou hranu vedoucí z~$\pi$ 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,
+\:::Pokud nenásleduje, tak nebyl pøítomen, èili tuto hranu rozdìlíme: pøidáme na~ni 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.
@@ -295,7 +298,7 @@ bude hodit p
 \::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.
+\::Kanonikalizace stejnì jako v~bodech 12--13.\foot{Dokonce jednodu¹¹í, proto¾e projdeme nejvý¹e jednu hranu.}
 \: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