From: Martin Mares Date: Tue, 9 Feb 2010 15:16:51 +0000 (+0100) Subject: Korektury od Martina Pecky. X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=17c16306f3ab0894b13b5552c752bac4c43205e4;p=ads2.git Korektury od Martina Pecky. --- diff --git a/1-toky/1-toky.tex b/1-toky/1-toky.tex index 38286d4..bacf36d 100644 --- a/1-toky/1-toky.tex +++ b/1-toky/1-toky.tex @@ -119,7 +119,7 @@ $$f(A,B) = \sum_{e \in (A,B)}{f(e)} - \sum_{e \in E(B,A)}{f(e)} \leq \sum_{e \in \proof{Indukcí a~obrázkem.} -Zaèneme s øezem ($V \setminus \{s\}, \{s\}$). Pro~tento øez lemma platí z~definice velikosti toku. Dále budu postupnì pøesouvat vrcholy z~mno¾iny $B$ do~mno¾iny $A$. Libovolý øez mù¾e být takto vytvoøen z~toho triviálního. +Zaèneme s øezem ($V \setminus \{s\}, \{s\}$). Pro~tento øez lemma platí z~definice velikosti toku. Dále budu postupnì pøesouvat vrcholy z~mno¾iny $B$ do~mno¾iny $A$. Libovolný øez mù¾e být takto vytvoøen z~toho triviálního. Pøedstavme si, ¾e~máme ji¾ libovolný øez ($A,B$) a~pøesouváme vrchol $v$ z~$A$ do~$B$. Tedy $A' = A \setminus \{v\}$ a $B' = B \cup \{v\}$. @@ -180,7 +180,7 @@ To, \s{Definice:} Párování je maximální, pokud obsahuje nejvìt¹í mo¾ný poèet hran. -Mìjme bipartitní graf $G = (V,E)$. V~nìm hledáme maximální párování. Sestrojme si~sí» takovou, ¾e~vezmeme vrcholy $V$ grafu $G$ a~pøidáme k~nim dva speciální vrcholy $z$ (zdroj) a~$s$ (stok) a~ze~zdroje pøidáme hrany do~v¹ech vrcholù levé partity a~ze~v¹ech vrcholù pravé partity povedeme hrany do~stoku. V¹echny kapacity nastavme na~1. Hrany bipartitního grafu zorientujme z levé partity do pravé. Nyní staèí jen na~tuto sí» spustit Fordùv-Fulkersonùv algoritmus (nebo libovolný jiný algoritmus, který najde maximální celoèíselný tok) a~a¾~dobìhne, tak prohlásit hrany s~kapacitami 1 za~maximální párování. +Mìjme bipartitní graf $G = (V,E)$. V~nìm hledáme maximální párování. Sestrojme si~sí» takovou, ¾e~vezmeme vrcholy $V$ grafu $G$ a~pøidáme k~nim dva speciální vrcholy $z$ (zdroj) a~$s$ (stok) a~ze~zdroje pøidáme hrany do~v¹ech vrcholù levé partity a~ze~v¹ech vrcholù pravé partity povedeme hrany do~stoku. V¹echny kapacity nastavme na~1. Hrany bipartitního grafu zorientujme z levé partity do pravé. Nyní staèí jen na~tuto sí» spustit Fordùv-Fulkersonùv algoritmus (nebo libovolný jiný algoritmus, který najde maximální celoèíselný tok) a~a¾~dobìhne, tak prohlásit hrany s~tokem 1 za~maximální párování. \figure{toky04.eps}{Hledání maximálního párování v~bipartitním grafu.}{2in} diff --git a/10-prevody/10-prevody.tex b/10-prevody/10-prevody.tex index 4721c29..070d102 100644 --- a/10-prevody/10-prevody.tex +++ b/10-prevody/10-prevody.tex @@ -162,8 +162,9 @@ takov \>Uká¾eme, jak na~tento probém pøevést 3-SAT. -\s{Pøevod 3-SAT na NzMna:} Z ka¾dé klauzule vybereme jeden literál tak, abychom v~rùzných -klauzulích nevybírali konfliktnì, tj.~$x$ a~$\lnot x$. +\s{Pøevod 3-SAT na NzMna:} Z ka¾dé klauzule vybereme jeden literál, jeho¾ nastavením se klauzuli +rozhodneme splnit. Samozøejmì tak, abychom v~rùzných klauzulích nevybírali +konfliktnì, tj.~$x$ a~$\lnot x$. \s{Pøíklad:} $(x \lor y \lor z) \land (x \lor \lnot y \lor \lnot z) \land (\lnot x \lor \lnot y \lor p) $. @@ -172,7 +173,7 @@ $(x \lor y \lor z) \land (x \lor \lnot y \lor \lnot z) \land (\lnot x \lor \lnot hrany, tj. $x$ a $\lnot x$. Poèet vrcholù grafu odpovídá poètu literálù ve formuli, poèet hran je maximálnì kvadratický a pøevod je tedy polynomiální. -Existuje-li v grafu nezávislá mno¾ina velikosti $k$, pak z právì $k$ trojúhelníkù +Existuje-li v grafu nezávislá mno¾ina velikosti $k$, pak z~ka¾dého z~$k$ trojúhelníkù vybere právì jeden vrchol, a pøitom ¾ádné dva vrcholy nebudou odpovídat literálu a jeho negaci -- tedy dostaneme ohodnocení promìnných splòujících alespoò $k$ klauzulí. Na druhou stranu, existuje-li ohodnocení $k$ klauzulí, pak pøímo odpovídá nezávislé @@ -207,10 +208,10 @@ vadit nebudou. \:A~nakonec si ohlídáme, aby v~ka¾dém øádku byla alespoò jedna jednièka, klauzulí $\forall i : x_{i1} \lor x_{i2} \lor \ldots \lor x_{in}$. \endlist -Tímto vynutíme NezMnu $\geq k$, co¾ jsme pøesnì chtìli. Takovýto pøevod je zøejmì polynomiální. +Tímto vynutíme NzMnu $\geq k$, co¾ jsme pøesnì chtìli. Takovýto pøevod je zøejmì polynomiální. \s{Pøíklad matice:} Jako pøíklad pou¾ijeme nezávislou mno¾inu z ukázky nezávislé mno¾iny. -Nech» jsou vrcholy grafu oèíslované zleva a zezhora. Hledáme nezávislou mno¾inu velikosti $2$. +Nech» jsou vrcholy grafu oèíslované zleva a zeshora. Hledáme nezávislou mno¾inu velikosti $2$. Matice pak bude vypadat následovnì: $$ \pmatrix{1&0&0&0&0 \cr 0&0&0&1&0}$$ \s{Vysvìtlení:} Jako první vrchol mno¾iny bude vybrán vrchol $v_1$, proto v prvním diff --git a/11-np/11-np.tex b/11-np/11-np.tex index 17b50d5..171e51d 100644 --- a/11-np/11-np.tex +++ b/11-np/11-np.tex @@ -5,7 +5,7 @@ Dosud jsme zkoumali problémy, které se nás ptaly na to, jestli nìco existuje. Napøíklad jsme dostali formuli a problém splnitelnosti se nás ptal, zda -existuje ohodnocení promìnných takové, ¾e formule platí. Nebo v~pøípade +existuje ohodnocení promìnných takové, ¾e formule platí. Nebo v~pøípadì nezávislých mno¾in jsme dostali graf a èíslo $k$ a ptali jsme se, jestli v~grafu existuje nezávislá mno¾ina, která obsahuje alespoò~$k$ vrcholù. Tyto otázky mìly spoleèné to, ¾e kdy¾ nám nìkdo napovìdìl nìjaký objekt, umìli @@ -85,7 +85,7 @@ d Napøíklad nezávislá mno¾ina, rùzné varianty SATu, klika v~grafu~\dots Jak taková tøída NP vypadá? Pøedstavme si v¹echny problémy tøídy NP, jakoby seøazené -zhora dolu podle obtí¾nosti problémù (tedy navzdor gravitaci), kde porovnání dvou +shora dolu podle obtí¾nosti problémù (tedy navzdor gravitaci), kde porovnání dvou problémù urèuje pøevoditelnost (viz obrázek). \figure{p-np.eps}{Struktura tøídy NP}{2.5cm} diff --git a/12-apx/12-apx.tex b/12-apx/12-apx.tex index 193bb49..aa6fb39 100644 --- a/12-apx/12-apx.tex +++ b/12-apx/12-apx.tex @@ -181,7 +181,7 @@ $(1+\varepsilon)$-aproxima \proof Uká¾eme, ¾e v~takovém pøípadì doká¾eme v~polynomiálním èase zjistit, zda v grafu existuje hamiltonovská kru¾nice. -\>Dostali jsme graf~$G$, v~kterém hledáme hamiltonovskou kru¾nici. Doplníme +\>Dostali jsme graf~$G$, ve~kterém hledáme hamiltonovskou kru¾nici. Doplníme $G$ na~úplný graf~$G'$ a~váhy hran~$G'$ nastavíme takto: \itemize\ibull \: $w(e) = 1$, kdy¾ $e \in E(G)$ @@ -190,7 +190,7 @@ $G$ na~ \>Konstantu $c$ potøebujeme zvolit tak velkou, abychom jasnì poznali, jestli je ka¾dá hrana z nalezené hamiltonovské kru¾nice hranou grafu $G$ (pokud by nebyla, bude kru¾nice obsahovat aspoò jednu hranu s váhou $c$, která vy¾ene -souèet poznatelnì vysoko). Pokuï existuje hamiltonovská kru¾nice v~$G'$ slo¾ená jen +souèet poznatelnì vysoko). Pokud existuje hamiltonovská kru¾nice v~$G'$ slo¾ená jen z~hran, které byly pùvodnì v~$G$, pak optimální øe¹ení bude mít váhu~$n$, jinak bude urèitì minimálnì $n-1+c$. Kdy¾ máme aproximaèní algoritmus s~pomìrem~$1+\varepsilon$, @@ -207,7 +207,7 @@ na~hamiltonovskou kru \s{Poznámka:} O existenci pseudopolynomiálního algoritmu platí analogická vìta, a doká¾e se analogicky -- existující hrany budou -mít hranu 1, neexistující váhu 2. +mít váhu 1, neexistující váhu 2. \h{Aproximaèní schéma pro problém batohu} diff --git a/2-dinic/2-dinic.tex b/2-dinic/2-dinic.tex index 311609e..244427c 100644 --- a/2-dinic/2-dinic.tex +++ b/2-dinic/2-dinic.tex @@ -48,8 +48,8 @@ Pro ka \:$g'(e) := g(e) - \delta$, \:$g'(\overleftarrow{e}) := g(\overleftarrow{e}) - \delta$. \endlist - - A tímto jsme to pøevedli na~nìkterý z~pøedchozích pøípadù, které u¾ umíme vyøe¹it. + + Tok $g'$ nyní spadá pod nìkterý z~pøedchozích pøípadù, které u¾ umíme vyøe¹it. \endlist @@ -82,7 +82,7 @@ Pro ka \:Teï musíme je¹tì dokázat, ¾e nový tok neporu¹uje Kirchhoffovy zákony: $$\forall v~\in V \setminus \{z,s\}: f'^\Delta(v)=0.$$ % neboli $$\forall v~\in V \setminus \{z,s\}: \sum_{u: uv \in E}{f'(uv)}=\sum_{u: vu \in E}{f'(vu)}.$$ - Vezmìme si~libovolnou hranu~$e = uv \in E$, ¾e $e=uv$. Uvìdomme si, ¾e pøi~pøechodu z~$f(e)$ na~$f'(e)$ a~z~$f(\overleftarrow{e})$ na~$f'(\overleftarrow{e})$ bylo: + Vezmìme si~libovolnou hranu~$e = uv \in E$. Uvìdomme si, ¾e pøi~pøechodu z~$f(e)$ na~$f'(e)$ a~z~$f(\overleftarrow{e})$ na~$f'(\overleftarrow{e})$ bylo: \itemize\idot \:$f^\Delta(u)$ sní¾eno o~$g(e)$ \:$f^\Delta(v)$ zvý¹eno o~$g(e)$. @@ -137,13 +137,13 @@ A te \algo \:Rozdìlíme vrcholy do~vrstev podle vzdálenosti od~$z$. -\:Odstraníme vrstvy za~$s$, hrany do~minulých vrstev a~hrany uvnitø vrstev. +\:Odstraníme vrstvy za~$s$ (tedy vrcholy, které jsou od~$z$ vzdálenìj¹í ne¾~$s$), hrany do~minulých vrstev a~hrany uvnitø vrstev. \:Odstraníme \uv{slepé ulièky}, tedy vrcholy s~$\deg^{out}(v) = 0$, a~to opakovanì pomocí fronty. (Nejdøíve zaøadíme do~fronty v¹echny vrcholy s~ $\deg^{out}(v) = 0$. Pak dokud není fronta prázdná, v¾dy vybereme vrchol~$v$ z~fronty, odstraníme~$v$ a~v¹echny hrany~$uv$. Pro~ka¾dý takový vrchol~$u$ zkontrolujeme, zda se~tím nesní¾il výstupní stupeò vrcholu~$u$ na~nulu ($\deg^{out}(u) = 0$). Pokud sní¾il, tak ho zaøadíme do~fronty.) \endalgo \figure{dinic-neprocistenasit.eps}{Neproèi¹tìná sí». Obsahuje zpìtné hrany, hrany uvnitø vrstvy a~slepé ulièky.}{0.45\hsize} -Hledání blokujícího toku zaèneme s~tokem nulovým. Pak vezmeme v¾dy orientovanou cestu ze~zdroje do~stoku v~síti~$C$. V~této cestì najdeme hranu s~nejni¾¹í hodnotou výrazu $r(e) - g(e)$ (neboli $c(e) - f(e)$ v~pùvodní síti). Tuto hodnotu oznaèíme~$\varepsilon$. Pak ke~ v¹em hranám pøièteme~$\varepsilon$. Pokud tok~$g$ na~nìjaké hranì dosáhne kapacity hrany, co¾ je zde~$r(e)$, tak hranu vyma¾eme. Následnì sí» doèistíme, aby splòovala podmínky vrstevnaté sítì. A~pokud je¹tì existuje nìjaká orientovaná cesta ze~zdroje do~stoku, tak opìt pokraèujeme s~touto cestou. +Hledání blokujícího toku zaèneme s~tokem nulovým. Pak vezmeme v¾dy orientovanou cestu ze~zdroje do~stoku v~síti~$C$. V~této cestì najdeme hranu s~nejni¾¹í hodnotou výrazu $r(e) - g(e)$ (neboli $c(e) - f(e)$ v~pùvodní síti). Tuto hodnotu oznaèíme~$\varepsilon$. Pak ke~ v¹em hranám na~této cestì pøièteme~$\varepsilon$. Pokud tok~$g$ na~nìjaké hranì dosáhne kapacity hrany, co¾ je zde~$r(e)$, tak hranu vyma¾eme. Následnì sí» doèistíme, aby splòovala podmínky vrstevnaté sítì. A~pokud je¹tì existuje nìjaká orientovaná cesta ze~zdroje do~stoku, tak opìt pokraèujeme s~touto cestou. \s{Algoritmus hledání blokujícího toku} @@ -159,7 +159,7 @@ Hled \s{Èasová slo¾itost} Rozeberme si~jednotlivé kroky algoritmu. \numlist{\ndotted} -\:Inicializace toku~$f$ \dots $\O(1)$. +\:Inicializace toku~$f$ \dots $\O(m)$. \:Sestrojení sítì rezerv a~smazání hran s~nulovou rezervou \dots $\O(m + n)$. \:Najití nejkrat¹í cesty (prohledáváním do~¹íøky) \dots $\O(m + n)$. \:Zkontrolování délky nejkrat¹í cesty \dots $\O(1)$. @@ -171,7 +171,7 @@ Hled \endlist \:Najití blokujícího toku~$g$ \dots $\O(m \cdot n)$. \numlist{\ndotted} - \:Inicializace toku~$g$ \dots $\O(1)$. + \:Inicializace toku~$g$ \dots $\O(m)$. \:Najití orientované cesty v~proèi¹tìné síti rezerv (staèí vzít libovolnou cestu ze~zdroje, nebo» ka¾dá z~nich v~této síti vede do~stoku) \dots $\O(n)$. \:Výbìr minima z~výrazu $r(e) - g(e)$ pøes v¹echny hrany cesty -- ta mù¾e být dlouhá nejvý¹e~$n$ \dots $\O(n)$. \:Pøepoèítání v¹ech hran cesty \dots $\O(n)$. @@ -200,9 +200,9 @@ Uv Podíváme se~na~prùbìh jednoho prùchodu vnìj¹ím cyklem. Délku aktuálnì nejkrat¹í cesty ze~zdroje do~stoku oznaème~$l$. V¹echny pùvodní cesty délky~$l$ se~bìhem prùchodu zaruèenì nasytí, proto¾e tok~$g$ je blokující. Musíme v¹ak dokázat, ¾e nemohou vzniknout ¾ádné nové cesty délky~$l$ nebo men¹í. V~síti rezerv toti¾ mohou hrany nejen ubývat, ale i~pøibývat: pokud po¹leme tok po~hranì, po~které je¹tì nic neteklo, tak v~protismìru z~dosud nulové rezervy vyrobíme nenulovou. Rozmysleme si~tedy, jaké hrany mohou pøibývat. -Hrany mohou pøibývat jen tehdy, kdy¾ jsme po~opaèné hranì nìco poslali. Ale my nìco posíláme po~hranách pouze z~vrstvy do~té následující. Hrany tedy pøibývají do~minulé vrstvy.. +Hrany mohou pøibývat jen tehdy, kdy¾ jsme po~opaèné hranì nìco poslali. Ale my nìco posíláme po~hranách pouze z~vrstvy do~té následující. Hrany tedy pøibývají do~minulé vrstvy. -Vznikem nových hran by proto mohly vzniknout nové cesty ze~zdroje do~stoku, které pou¾ívají zpìtné hrany. Jen¾e cesta ze~zdroje do~stoku, která pou¾ije zpìtnou hranu, musí alespoò jednou skoèit o~vrstvu zpìt a~nikdy nemù¾e skoèit o~více ne¾ jednu vrstvu dopøedu, a~proto je její délka alespoò $l+2$. Pokud cesta novou zpìtnou hranu nepou¾ije má buï délku~$> l$, co¾ je v~poøádku, nebo má délku~$= l$, pak je zablokovaná. +Vznikem nových hran by proto mohly vzniknout nové cesty ze~zdroje do~stoku, které pou¾ívají zpìtné hrany. Jen¾e cesta ze~zdroje do~stoku, která pou¾ije zpìtnou hranu, musí alespoò jednou skoèit o~vrstvu zpìt a~nikdy nemù¾e skoèit o~více ne¾ jednu vrstvu dopøedu, a~proto je její délka alespoò $l+2$. Pokud cesta novou zpìtnou hranu nepou¾ije, má buï délku~$> l$, co¾ je v~poøádku, nebo má délku~$= l$, pak je zablokovaná. Tím je lemma dokázáno. \qed diff --git a/3-goldberg/3-goldberg.tex b/3-goldberg/3-goldberg.tex index 9c5db3b..70544d4 100644 --- a/3-goldberg/3-goldberg.tex +++ b/3-goldberg/3-goldberg.tex @@ -174,7 +174,7 @@ D \s{Rozbor èasové slo¾itosti algoritmu:} \numlist\ndotted -\:Inicializace vý¹ek \dots\ $\O(1)$. +\:Inicializace vý¹ek \dots\ $\O(N)$. \:Inicializace vlny~$f$ \dots\ $\O(M)$. \:Výbìr vrcholu~$u$ s~kladným pøebytkem -- vezmeme první vrchol v~$P$ \dots\ $\O(1)$. \:Výbìr vrcholu~$v$, do~kterého vede z~$u$ hrana s~kladnou rezervou a~který je ní¾e ne¾~$u$ -- vezmeme první hranu z~$L(u)$ \dots\ $\O(1)$. @@ -239,7 +239,7 @@ Rozmysleme si, o~kolik bude vylep \proof Dokazovat budeme opìt pomocí potenciálové metody. Zadefinujme si~potenciál {\I nejvy¹¹í hladinu s~pøebytkem}: $$H := \max \{ h(v) \mid v \neq z,s ~\&~ f^\Delta(v) > 0\}.$$ -Rozdìlíme bìh algoritmu na~{\I fáze}. Ka¾dá fáze konèí tím, ¾e~se~$H$ zmìní. Jak se~mù¾e zmìnit? Buï se~$H$ zvý¹í, co¾ znamená, ¾e~nìjaký vrchol s~pøebytkem v~nejvy¹¹í hladinì byl o~1 zvednut, nebo se~$H$ sní¾í. My víme, ¾~ zvednutí je v~celém algoritmu $\O(N^2)$. Zároveò si~mù¾eme uvìdomit, ¾e~$H$ je nezáporný potenciál, kdy sní¾ení i~zvý¹ení ho zmìní o~1, tedy poèet sní¾ení bude stejný jako poèet zvý¹ení, a~proto obojího je~$\O(N^2)$. Tudí¾ poèet fází je také~$\O(N^2)$. +Rozdìlíme bìh algoritmu na~{\I fáze}. Ka¾dá fáze konèí tím, ¾e~se~$H$ zmìní. Jak se~mù¾e zmìnit? Buï se~$H$ zvý¹í, co¾ znamená, ¾e~nìjaký vrchol s~pøebytkem v~nejvy¹¹í hladinì byl o~1 zvednut, nebo se~$H$ sní¾í. My víme, ¾e zvednutí je v~celém algoritmu $\O(N^2)$. Zároveò si~mù¾eme uvìdomit, ¾e~$H$ je nezáporný potenciál, kdy sní¾ení i~zvý¹ení ho zmìní o~1, tedy poèet sní¾ení bude stejný jako poèet zvý¹ení, a~proto obojího je~$\O(N^2)$. Tudí¾ poèet fází je také~$\O(N^2)$. Je dùle¾ité, ¾e~bìhem jedné fáze provedeme nejvý¹e jedno nenasycené pøevedení z~ka¾dého vrcholu. Po~ka¾dém nenasyceném pøevedení po~hranì $uv$ se~toti¾ vynuluje pøebytek v~$u$ a~aby se~provedlo dal¹í nenasycené pøevedení z~vrcholu~$u$, muselo by nejdøíve být co~pøevádìt. Muselo by tedy do~$u$ nìco pøitéci. My ale víme, ¾e pøevádíme pouze shora dolù a~$u$ je v~nejvy¹¹í hladinì (to zajistí právì to vylep¹ení algoritmu), tedy nejdøíve by musel být nìjaký jiný vrchol zvednut. Tím by se~ale zmìnilo~$H$ a~skonèila by tato fáze. @@ -271,7 +271,7 @@ Tedy plat \endlist Uvìdomme si, ¾e~pokud pøevádíme po~hranì~$uv$, tak platí, ¾e~$h(u) = h(v) + 1$. Pak~$p(u) - p(v)$ je pøesnì poèet vrcholù na~hladinì~$H$. Tìch je alespoò tolik, kolik je nenasycených pøevedení bìhem jedné fáze (to jsme dokázali ji¾ v~lemmatu N'), a~my jsme si~zadefinovali, ¾e v~drahé fázi je poèet nenasycených pøevedení alespoò~$K$. Tedy~$p(u) - p(v) > K$. Proto bìhem jednoho nenasyceného pøevedení~$\Phi$ klesne alespoò o~${K \over K} = 1$. Nenasycená pøevedení potenciál nezvy¹ují. -Potenciál~$\Phi$ se~mù¾e zvìt¹it pouze pøi~operacích zvednutí a~nasycené pøevý¹ení. Zvednutí se~provede celkem~$(N^2)$ a~ka¾dé zvý¹í potenciál nejvý¹e o~$N \over K$. Nasycených pøevedení se provede celkem~$\O(NM)$ a~ka¾dé zvý¹í potenciál takté¾ nejvý¹e o~$N \over K$. Celkem se~tedy~$\Phi$ zvý¹í nejvý¹e o +Potenciál~$\Phi$ se~mù¾e zvìt¹it pouze pøi~operacích zvednutí a~nasycené pøevedení. Zvednutí se~provede celkem~$\O(N^2)$ a~ka¾dé zvý¹í potenciál nejvý¹e o~$N \over K$. Nasycených pøevedení se provede celkem~$\O(NM)$ a~ka¾dé zvý¹í potenciál takté¾ nejvý¹e o~$N \over K$. Celkem se~tedy~$\Phi$ zvý¹í nejvý¹e o $${N \over K} \O(N^2) + {N \over K} \O(NM) = \O \left({N^3 \over K} + {N^2M \over K}\right).$$ Teï vyu¾ijeme toho, ¾e~$\Phi$ je nezáporný potenciál, tedy kdy¾ ka¾dé nenasycené pøevdení v~drahé fázi sní¾í~$\Phi$ alespoò o~1, tak v¹ech nenasycených pøevdení v~drahých fázích je~$\O({N^3 \over K} + {N^2M \over K})$. U¾ jsme ukázali, ¾e~nenasycených pøevední v~laciných fázích je~$\O(N^2K)$. Proto celkem v¹ech nenasycených pøevedení je diff --git a/5-addsort/5-addsort.tex b/5-addsort/5-addsort.tex index 1bc41dd..9c64855 100644 --- a/5-addsort/5-addsort.tex +++ b/5-addsort/5-addsort.tex @@ -12,7 +12,7 @@ se K tomuto úèelu se~ihned nabízí pou¾ít starý dobrý \uv{¹kolní algoritmus}, který funguje ve~dvojkové soustavì stejnì dobøe jako v~desítkové. Zkrátka sèítáme èísla -z~prava doleva. V¾dy seèteme pøíslu¹né èíslice pod~sebou a~pøièteme pøenos z~ni¾¹ího +zprava doleva. V¾dy seèteme pøíslu¹né èíslice pod~sebou a~pøièteme pøenos z~ni¾¹ího øádu. Tím dostaneme jednu èíslici výsledku a~pøenos do~vy¹¹ího øádu. Formálnì bychom to mohli zapsat tøeba takto: $$ @@ -217,7 +217,7 @@ Jak je vid setøídí na~$\Theta(\log n)$ hladin. Nyní se dá odvodit, ¾e pokud umíme tøídit bitonické posloupnosti, umíme setøídit v¹echno. -Vzpomeòme si na~tøídìní sléváním -- Merge sort. To funguje tak, ¾e zaène s~jednoprvkovými posloupnostmi, které jsou evidentnì setøídìné, a~poté v¾dy dvì setøídìné posloupnosti slývá do~jedné. Kdybychom nyní umìli paralelnì slévat, mohli bychom vytvoøit i~paralelní Merge sort. Jinými slovy, potøebujeme dvì rostoucí posloupnosti nìjak efektivnì slít do~jedné setøídìné. Uvìdomme si, ¾e to zvládneme jednodu¹e -- staèí druhou z~posloupností obrátit a~\uv{pøilepit} za~první, èím¾ vznikne bitonická posloupnost, kterou poté mù¾eme setøídit na¹í bitonickou tøídièkou. +Vzpomeòme si na~tøídìní sléváním -- Merge sort. To funguje tak, ¾e zaène s~jednoprvkovými posloupnostmi, které jsou evidentnì setøídìné, a~poté v¾dy dvì setøídìné posloupnosti slévá do~jedné. Kdybychom nyní umìli paralelnì slévat, mohli bychom vytvoøit i~paralelní Merge sort. Jinými slovy, potøebujeme dvì rostoucí posloupnosti nìjak efektivnì slít do~jedné setøídìné. Uvìdomme si, ¾e to zvládneme jednodu¹e -- staèí druhou z~posloupností obrátit a~\uv{pøilepit} za~první, èím¾ vznikne bitonická posloupnost, kterou poté mù¾eme setøídit na¹í bitonickou tøídièkou. \s{Pøíklad:} {\sl Merge sort} diff --git a/6-kmp/6-kmp.tex b/6-kmp/6-kmp.tex index 288b2a2..041c06a 100644 --- a/6-kmp/6-kmp.tex +++ b/6-kmp/6-kmp.tex @@ -18,7 +18,7 @@ M \h{Pomalý algoritmus} Zkusíme algoritmus vylep¹it tak, aby fungoval správnì: pokud nastane nìjaká neshoda, vrátíme se zpátky tìsnì za~zaèátek toho, kdy se nám to zaèalo shodovat. To je ov¹em vlastnì skoro toté¾, jako brát postupnì v¹echny mo¾né zaèátky v~\uv{senì} a~pro ka¾dý z~nìj ovìøit, jestli se tam \uv{jehla} nachází èi nikoliv. -Tento algoritmus evidentnì funguje. Bì¾í v¹ak v~èase: $S$ mo¾ných zaèátkù, krát èas potøebný na~jedno porovnání (zda se na~dané pozici nenachází \uv{jehla}), co¾ nám mù¾e trvat a¾ $J$. Proto je èasová slo¾itost $\O(SJ)$. V praxi bude algoritus èasto rychlej¹í, proto¾e typicky velmi brzo zjistíme, ¾e se øetìzce neshodují, ale je mo¾né vymyslet vstup, kde bude potøeba porovnání opravdu tolik. +Tento algoritmus evidentnì funguje. Bì¾í v¹ak v~èase: $S$ mo¾ných zaèátkù, krát èas potøebný na~jedno porovnání (zda se na~dané pozici nenachází \uv{jehla}), co¾ nám mù¾e trvat a¾ $J$. Proto je èasová slo¾itost $\O(SJ)$. V praxi bude algoritmus èasto rychlej¹í, proto¾e typicky velmi brzo zjistíme, ¾e se øetìzce neshodují, ale je mo¾né vymyslet vstup, kde bude potøeba porovnání opravdu tolik. Nyní se pokusme najít takový algoritmus, který by byl tak rychlý, jako {\I Hloupý algoritmus}, ale chytrý, jako ten {\I Pomalý}. @@ -59,13 +59,13 @@ Aby se n \endlist -V¹imnìme si, ¾e prázdné slovo je prefixem, suffixem i~podslovem jekéhokoliv slova vèetnì sebe sama. +V¹imnìme si, ¾e prázdné slovo je prefixem, suffixem i~podslovem jakéhokoliv slova vèetnì sebe sama. Ka¾dé slovo je také prefixem, suffixem i~podslovem sebe sama. To se ne v¾dy hodí. Nìkdy budeme chtít øíct, ¾e nìjaké slovo je {\I vlastním} prefixem nebo suffixem. To bude znamenat, ¾e to nebude celé slovo. \> $\alpha$ je {\I vlastní prefix} slova $\beta \equiv \alpha$ je prefix $\beta~\&~\alpha \neq \beta$. \h{Vyhledávací automat (Knuth, Morris, Pratt)} -{\I Vyhledávací automat} bude graf, jeho¾ vrcholùm budeme øíkat {\I stavy}. Jejich jména budou prefixy hledaného slova a~hrany budou odpovídat tomu, jak jeden prefix mù¾eme získat z~pøedchozího prefixu pøidáním jednoho stavu. Poèáteèní stav je prázdné slovo $\varepsilon$ a~koncový je celá $\iota$. Dopøedné hrany grafu budou popisovat pøechod mezi stavy ve~smyslu zvìt¹ení délky jména stavu (dopøedná funkce $h(\alpha)$, urèující znak na~dopøedné hranì z~$\alpha$). Zpìtné hrany grafu budou popisovat pøechod (zpìtná funkce $z(\alpha)$) mezi stavem $\alpha$ a~nejdel¹ím vlastním suffixem $\alpha$, který je prefixem $\iota$, kdy¾ nastane neshoda. +{\I Vyhledávací automat} bude graf, jeho¾ vrcholùm budeme øíkat {\I stavy}. Jejich jména budou prefixy hledaného slova a~hrany budou odpovídat tomu, jak jeden prefix mù¾eme získat z~pøedchozího prefixu pøidáním jednoho písmene. Poèáteèní stav je prázdné slovo $\varepsilon$ a~koncový je celá $\iota$. Dopøedné hrany grafu budou popisovat pøechod mezi stavy ve~smyslu zvìt¹ení délky jména stavu (dopøedná funkce $h(\alpha)$, urèující znak na~dopøedné hranì z~$\alpha$). Zpìtné hrany grafu budou popisovat pøechod (zpìtná funkce $z(\alpha)$) mezi stavem $\alpha$ a~nejdel¹ím vlastním suffixem $\alpha$, který je prefixem $\iota$, kdy¾ nastane neshoda. \figure{barb.eps}{Vyhledávací automat.}{4.1in} @@ -122,7 +122,7 @@ Nyn \s{Pozorování:} Pøedstavme si, ¾e automat u¾ máme hotový a~tím, ¾e budeme sledovat jeho chování, chceme zjistit, jak v~nìm vedou zpìtné hrany. Vezmìme si nìjaký stav~$\beta$. To, kam z~nìj vede zpìtná hrana zjistíme tak, ¾e spustíme automat na~øetìzec $\beta$~bez prvního písmenka a~stav, ve~kterém se automat zastaví, je pøesnì ten, kam má vést i~zpìtná hrana z~$\beta$. Jinými slovy víme, ¾e $z(\beta) = \alpha (\beta[1:])$. -Proè takováto vìc funguje? V¹imìme si, ¾e definice $z$ a~to, co nám o~$\alpha$ øíká invariant je témìø toto¾ná -- $z(\beta)$ je nejdel¹í vlastní suffix $\beta$, který je stavem, $\alpha(\beta)$ je nejdel¹í suffix $\beta$, který je stavem. Jediná odli¹nost je v~tom, ¾e definice $z$ narozdíl od~definice $\alpha$ zakazuje nevlastní suffixy. Jak nyní vylouèit suffix $\beta$, který by byl roven $\beta$ samotné? Zkrátíme $\beta$ o~první znak. Tím pádem v¹echny suffixy $\beta$ bez prvního znaku jsou stejné jako v¹echny vlastní suffixy $\beta$. +Proè takováto vìc funguje? V¹imìme si, ¾e definice $z$ a~to, co nám o~$\alpha$ øíká invariant, je témìø toto¾né -- $z(\beta)$ je nejdel¹í vlastní suffix $\beta$, který je stavem, $\alpha(\beta)$ je nejdel¹í suffix $\beta$, který je stavem. Jediná odli¹nost je v~tom, ¾e definice $z$ narozdíl od~definice $\alpha$ zakazuje nevlastní suffixy. Jak nyní vylouèit suffix $\beta$, který by byl roven $\beta$ samotné? Zkrátíme $\beta$ o~první znak. Tím pádem v¹echny suffixy $\beta$ bez prvního znaku jsou stejné jako v¹echny vlastní suffixy $\beta$. K èemu je toto pozorování dobré? Rozmysleme si, ¾e pomocí nìj u¾ doká¾eme zkonstruovat zpìtné hrany. Není to ale trochu divné, kdy¾ pøi simulování automatu na~øetìzec bez prvního znaku u¾ zpìtné hrany potøebujeme? Není. Za chvíli zjistíme, ¾e takto mù¾eme zji¹»ovat zpìtné hrany postupnì -- a~to tak, ¾e pou¾íváme v¾dy jenom ty, které jsme u¾ sestrojili. @@ -131,7 +131,7 @@ V Nabízí se tedy zaèít zpìtnou hranou z~prvního znaku (která vede evidentnì do~$\varepsilon$), pak postupnì brát dal¹í stavy a~pro ka¾dý z~nich si spoèítat, kdy spustíme automat na~jméno stavu bez prvního znaku a~tím získáme dal¹í zpìtnou hranu. Toto funguje, ale je to kvadratické \dots. Máme toti¾ $J$ stavù a~pro ka¾dý z~nich nám automat bì¾í v~èase a¾ lineárním s~$J$. Jak z~toho ven? -Z~prvního stavu povede zpìtná funkce do~$\varepsilon$. Pro dal¹í stavy chceme spoèítat zpìtnou funkci. Z~druhého stavu $\iota[0:2]$ tedy automat spustíme na~$\iota[1:2]$, dále pak na~$\iota[1:3]$, $\iota[1:4]$, atd. Ty øetìzce, pro které potøebujeme spo¹tìt automat, abychom dostali zpìtné hrany, jsou tedy ve~skuteènosti takové, ¾e ka¾dý dal¹í dostaneme roz¹íøením pøedchozího o~jeden znak. To jsou ale pøesnì ty stavy, kterými projde automat pøi zpracovávání øetezce $\iota$ od~prvního znaku dál. Jedním prùchodem automatu nad jehlou bez prvního písmenka se tím pádem rovnou dozvíme v¹echny údaje, které potøebujeme. +Z~prvního stavu povede zpìtná funkce do~$\varepsilon$. Pro dal¹í stavy chceme spoèítat zpìtnou funkci. Z~druhého stavu $\iota[0:2]$ tedy automat spustíme na~$\iota[1:2]$, dále pak na~$\iota[1:3]$, $\iota[1:4]$, atd. Ty øetìzce, pro které potøebujeme spo¹tìt automat, abychom dostali zpìtné hrany, jsou tedy ve~skuteènosti takové, ¾e ka¾dý dal¹í dostaneme roz¹íøením pøedchozího o~jeden znak. To jsou ale pøesnì ty stavy, kterými projde automat pøi zpracovávání øetìzce $\iota$ od~prvního znaku dál. Jedním prùchodem automatu nad jehlou bez prvního písmenka se tím pádem rovnou dozvíme v¹echny údaje, které potøebujeme. Z~pøedchozího pozorování plyne, ¾e nikdy nebudeme potøebovat zpìtnou hranu, kterou jsme je¹tì nezkonstruovali a~jeliko¾ víme, ¾e jedno prohledání trvá lineárnì s~délkou toho, v~èem hledáme, tak toto celé pobì¾í v~lineárním èase. Dostaneme tedy následující algoritmus: \s{Konstrukce zpìtné funkce:} @@ -156,7 +156,7 @@ Line Nyní si uká¾eme je¹tì jeden algoritmus na~hledání jedné jehly, který nebude mít v~nejhor¹ím pøípadì lineární slo¾itost, ale bude ji mít prùmìrnì. Bude daleko jednodu¹¹í a~uká¾e se, ¾e je v~praxi daleko rychlej¹í. Bude to algoritmus zalo¾ený na~hashování. -Pøedstavme si, ¾e máme seno délky $S$ a~jehlu délky $J$, a~vezmìme si nìjakou hashovací funkci, které dáme na~vstup $J$-tici znakù (tedy podslova dlouhá jako jehla). Tato hashovací funkce nám je pak zobrazí do~nìjaké velké mno¾iny èísel. Jak nám toto pomù¾e pøi hledání jehly? Vezmeme si libovolné \uv{okénko} délky $J$ a~ne¾ budeme zji¹»ovat, zda se v~nìm jehla vyskytuje, tak si spoèítáme hashovací funkci a~porovnáme ji s~hashem jehly. Èili ptáme se, jestli je hash ze sena od~nìjaké pozice $I$ do~pozice $I+J$ roven hashi jehly -- formálnì: $h(\sigma [I: I+J ]) = h(\iota)$. Teprve tehdy, kdy¾ zjistíme, ¾e se hodnota hashovací fce shoduje, zaèneme doopravdy porovnávat øetìzce. +Pøedstavme si, ¾e máme seno délky $S$ a~jehlu délky $J$, a~vezmìme si nìjakou hashovací funkci, které dáme na~vstup $J$-tici znakù (tedy podslova dlouhá jako jehla). Tato hashovací funkce nám je pak zobrazí do~mno¾iny $\{0,\ldots,N-1\}$ pro nìjaké dost velké~$N$. Jak nám toto pomù¾e pøi hledání jehly? Vezmeme si libovolné \uv{okénko} délky $J$ a~ne¾ budeme zji¹»ovat, zda se v~nìm jehla vyskytuje, tak si spoèítáme hashovací funkci a~porovnáme ji s~hashem jehly. Èili ptáme se, jestli je hash ze sena od~nìjaké pozice $I$ do~pozice $I+J$ roven hashi jehly -- formálnì: $h(\sigma [I: I+J ]) = h(\iota)$. Teprve tehdy, kdy¾ zjistíme, ¾e se hodnota hashovací fce shoduje, zaèneme doopravdy porovnávat øetìzce. Není to ale nìjaká hloupost? Mù¾e nám vùbec takováto konstrukce pomoci? Není to tak, ¾e na~spoèítání hashovací funkce z~$J$ znakù, potøebujeme tìch $J$ znakù pøeèíst, co¾ je stejnì rychlé, jako rovnou øetìzce porovnávat? Pou¾ijeme trik, který bude spoèívat v~tom, ¾e si zvolíme ¹ikovnou hashovací funkci. Udìláme to tak, abychom ji mohli pøi posunutí \uv {okénka} o~jeden znak doprava v~konstantním èase pøepoèítat. Chceme umìt z~$h(x_1 \dots x_j)$ spoèítat $h(x_2 \dots x_{j+1})$. Na~zaèátku si tedy spoèítáme hash jehly a~první $J$-tice znakù sena. Pak ji¾ jenom posouváme \uv {okénko} o~jedna, pøepoèítáme hashovací funkci a~kdy¾ se shoduje s~hashem jehly, tak porovnáme. Budeme pøitom vìøit tomu, ¾e pokud se tam jehla nevyskytuje, pak máme hashovací funkci natolik rovnomìrnou, ¾e pravdìpodobnost toho, ¾e se pøesto strefíme do~hashe jehly, je $1/N$. Jinými slovy jenom v~jednom z~øádovì $N$ pøípadù budeme porovnávat fale¹nì -- tedy provedeme porovnání a~vyjde nám, ¾e výsledek je neshoda. V~prùmìrném pøípadì tedy mù¾eme stlaèit slo¾itost a¾ témìø k~lineární. @@ -171,15 +171,15 @@ Po posunut $$(x_2 \cdot p^{J-1} + x_3 \cdot p^{J-2} + \dots + x_J \cdot p^1 + x_{J+1} \cdot p^0 ) \bmod N.$$ Kdy¾ se ale podíváme na~èleny tìchto dvou polynomù, zjistíme, ¾e se li¹í jen o~málo. Pùvodní polynom staèí pøenásobit~$p$, odeèíst první èlen s~$x_1$ a~naopak pøièíst chybìjící èlen $x_{J+1}$. Dostáváme tedy: $$h(x_2 \dots x_{J+1}) = (p \cdot h(x_1 \dots x_J) - x_1 \cdot p^J + x_{J+1}) \bmod N.$$ -Pøepoèítání hashovací funkce tedy není nic jiného, ne¾ pøenásobení té minulé~$p$, odeètení nìjakého násobku toho znaku, který vypadl z~okénka a~pøiètení toho znaku, o~který se okénko posunulo. Pokud tedy máme k~dispozici aritmetické operace v~konstantním èase, zvládneme konstantnì pøepoèítávat i~hashovací funkci. +Pøepoèítání hashovací funkce tedy není nic jiného, ne¾ pøenásobení té minulé~$p$, odeètení nìjakého násobku toho znaku, který vypadl z~okénka, a~pøiètení toho znaku, o~který se okénko posunulo. Pokud tedy máme k~dispozici aritmetické operace v~konstantním èase, zvládneme konstantnì pøepoèítávat i~hashovací funkci. -Tato hashovací funkce se dokonce nejen hezky poèítá, ale dokonce se i~opravdu \uv{hezky} chová (tedy \uv{rozumnì} náhodnì), pokud zvolíme vhodné~$p$. To bychom mìli zvoli tak, aby bylo rozhodnì nesoudìlné s~$N$ -- tedy $\(p, N) = 1$. Aby se nám navíc dobøe projevilo modulo obsa¾ené v~hashovací funkci, mìlo by být~$p$ relativnì velké (lze dopoèítat, ¾e optimum je mezi $2/3 \cdot N$ a~$3/4 \cdot N$). S~takto zvoleným~$p$ se tato hashovací funkce chová velmi pøíznivì a~v~praxi má celý algoritmus takøka lineární èasovou slo¾itost (prùmìrnou). +Tato hashovací funkce se dokonce nejen hezky poèítá, ale dokonce se i~opravdu \uv{hezky} chová (tedy \uv{rozumnì} náhodnì), pokud zvolíme vhodné~$p$. To bychom mìli zvolit tak, aby bylo rozhodnì nesoudìlné s~$N$ -- tedy $\(p, N) = 1$. Aby se nám navíc dobøe projevilo modulo obsa¾ené v~hashovací funkci, mìlo by být~$p$ relativnì velké (lze dopoèítat, ¾e optimum je mezi $2/3 \cdot N$ a~$3/4 \cdot N$). S~takto zvoleným~$p$ se tato hashovací funkce chová velmi pøíznivì a~v~praxi má celý algoritmus takøka lineární èasovou slo¾itost (prùmìrnou). \h{Hledání více øetìzcù najednou} Nyní si zahrajeme tuté¾ hru, ov¹em v~trochu slo¾itìj¹ích kulisách. Podíváme se na~algoritmus, který si poradí i~s více ne¾ jednou jehlou. Mìjme tedy jehly $\iota_1 \dots \iota_n$, a~jejich délky $J_i = \vert \iota_i \vert $. Dále budeme potøebovat seno $\sigma$ délky $S=\vert \sigma \vert$. -Pøedtím, ne¾ se pustíme do~vlastního vyhledávacího algoritmu, mo¾ná bychom si mìli ujasnit, co vlastnì bude jeho výstupem. U problému hledání jedné jehly to bylo jasné -- byla to nìjaká mno¾ina pozic v~senì, na~kterých zaèínaly výskyty jehly. Jak tomu ale bude zde? Sice bychom také mohly vrátit pouze mno¾inu pozic, ale my budeme chtít malièko víc. Budeme toti¾ chtít vìdìt i~to, která jehla se na~které pozici vyskytuje. Výstup tedy bude vypadat následovnì: $V = \{(i,j)~\vert~\sigma[i:i+J_j]= \iota_j \}$. +Pøedtím, ne¾ se pustíme do~vlastního vyhledávacího algoritmu, mo¾ná bychom si mìli ujasnit, co vlastnì bude jeho výstupem. U problému hledání jedné jehly to bylo jasné -- byla to nìjaká mno¾ina pozic v~senì, na~kterých zaèínaly výskyty jehly. Jak tomu ale bude zde? Sice bychom také mohli vrátit pouze mno¾inu pozic, ale my budeme chtít malièko víc. Budeme toti¾ chtít vìdìt i~to, která jehla se na~které pozici vyskytuje. Výstup tedy bude vypadat následovnì: $V = \{(i,j)~\vert~\sigma[i:i+J_j]= \iota_j \}$. Zde se v¹ak skrývá jedna drobná zrada. Budeme se asi muset vzdát nadìje, ¾e najdeme algoritmus, jeho¾ slo¾itost je lineární v~celkové délce v¹ech jehel a~sena. Výstup toti¾ mù¾e být del¹í ne¾ lineární. Mù¾e se nám klidnì stát, ¾e na~jedné pozici v~senì se bude vyskytovat více rùzných jehel -- pokud bude jedna jehla prefixem jiné (co¾ jsme nikde nezakázali), tak máme povinnost ohlásit oba výskyty. Vzhledem k~tomu budeme hledat takový algoritmus, který bude lineární v~délce vstupu plus délce výstupu, co¾ je evidentnì to nejlep¹í, èeho mù¾eme dosáhnout. @@ -203,7 +203,7 @@ Zb První, co se nabízí, je vyu¾ít toho, ¾e jsme si oznaèili nìjaké vrcholy, kde hledaná slova konèí. Co tedy zkusit hlásit výskyt tohoto slova v¾dy, kdy¾ pøijdeme do~nìjakého oznaèeného vrcholu? Tento zpùsob v¹ak nefunguje, pokud se uvnitø nìkteré jehly skrývá jehla vnoøená. Napøíklad po~pøeètení slova |bara|, nám ná¹ souèasný automat neøíká, ¾e bychom mìli nìjaké slovo ohlásit, a~pøitom tam evidentì konèí podøetìzec |ara|. Stejnì tak pokud pøeèteme |barbara|, u¾ si nev¹imneme toho, ¾e tam konèí zároveò i~|ara|. Pouhé \uv{hlá¹ení teèek} tedy nefunguje. -Dále si mù¾eme v¹imnout toho, ¾e v¹echna slova, která by se mìla v~daném stavu hlásit, jsou suffixy jména tohoto stavu. Pøi tom víme, ¾e zpìtná hrana jméno stavu zkracuje zleva. Tak¾e speciálnì v¹echny suffixy daného stavu, které jsou také stavy, se dají najít tak, ¾e se vydáme po~zpìtných hranách do~koøene. Nabízí se tedy v¾dy projít cestu po~zpìtných hranách a¾ do~koøene a~hlásit v¹echny \uv{teèky}. Tento zpùsob by nám v¹ak celý algoritmus znaènì zpomalilo, proto¾e cesta do~koøene mù¾e být relativnì dlouhá, ale teèek na~ní obvykle bude málo. +Dále si mù¾eme v¹imnout toho, ¾e v¹echna slova, která by se mìla v~daném stavu hlásit, jsou suffixy jména tohoto stavu. Pøitom víme, ¾e zpìtná hrana jméno stavu zkracuje zleva. Tak¾e speciálnì v¹echny suffixy daného stavu, které jsou také stavy, se dají najít tak, ¾e se vydáme po~zpìtných hranách do~koøene. Nabízí se tedy v¾dy projít cestu po~zpìtných hranách a¾ do~koøene a~hlásit v¹echny \uv{teèky}. Tento zpùsob by nám v¹ak celý algoritmus znaènì zpomalil, proto¾e cesta do~koøene mù¾e být relativnì dlouhá, ale teèek na~ní obvykle bude málo. Mohli bychom také zkusit si pro ka¾dý stav $\beta$ pøedpoèítat mno¾inu $cache(\beta)$, která by obsahovala v¹echna slova, která máme hlásit, kdy¾ se ve~stavu $\beta$ nacházíme. Pokud pak do~tohoto stavu vstoupíme, podíváme se na~tuto mno¾inu a~vypí¹eme v¹e, co v~ní je. Výpis nám bude evidentnì trvat lineárnì k~velikosti mno¾iny, celkovì tedy lineárnì k~velikosti výstupu. Problém je ale ten, ¾e jednotlivé cache mohou být hodnì velké, tak¾e je nestihneme sestrojit v lineárním èase. (Rozmyslete si pøíklad slovníku, kdy se to stane.) @@ -246,7 +246,7 @@ Nejprve si nadefinujeme, jak vypad Algoritmus hledání vlastnì není nic jiného, ne¾ prosté projití po~zelených zkratkových hranách ze stavu $\alpha$, ve~kterém právì jsme, a~ohlá¹ení v¹eho, co po~cestì najdeme. -V ka¾dém okam¾iku se automat nachází ve~stavu, který odpovídá nejmen¹ímu mo¾nému suffixu toho, co jsme u¾ pøeèetli. Dùkaz tohoto invariantu je stejný jako u verze automatu pro hledání pouze jedné jehly, nebo» vychází pouze z~definice zpìtných hran. Podobnì nahlédneme, ¾e èasová slo¾itost vyhledávací procedury je lineární v~délce sena plus to, co spotøebujeme na~hlá¹ení výskytù. Nejprve na~chvíli zapomeneme, ¾e nìjaké výskyty hlásíme a~spoèítáme jenom kroky. Ty mohou vést dopøedu a~zpátky. Krok dopøedu prodlu¾uje jméno stavu o~jedna, krok dozadu zkracuje aspoò o~jedna. Tudí¾ krokù dozadu je maximálnì tolik, co krokù dopøedu a~krokù dopøedu je maximálnì tolik, kolik je délka sena. V¹echny kroky dohromady tedy trvají $\O(S)$. Hlá¹ení výskytù pak trvá $\O(S~+ \vert V \vert)$. Celé hledání tedy trvá lineárnì v~délce vstupu a~výstupu. +V ka¾dém okam¾iku se automat nachází ve~stavu, který odpovídá nejdel¹ímu mo¾nému suffixu toho, co jsme u¾ pøeèetli. Dùkaz tohoto invariantu je stejný jako u verze automatu pro hledání pouze jedné jehly, nebo» vychází pouze z~definice zpìtných hran. Podobnì nahlédneme, ¾e èasová slo¾itost vyhledávací procedury je lineární v~délce sena plus to, co spotøebujeme na~hlá¹ení výskytù. Nejprve na~chvíli zapomeneme, ¾e nìjaké výskyty hlásíme a~spoèítáme jenom kroky. Ty mohou vést dopøedu a~zpátky. Krok dopøedu prodlu¾uje jméno stavu o~jedna, krok dozadu zkracuje aspoò o~jedna. Tudí¾ krokù dozadu je maximálnì tolik, co krokù dopøedu a~krokù dopøedu je maximálnì tolik, kolik je délka sena. V¹echny kroky dohromady tedy trvají $\O(S)$. Hlá¹ení výskytù pak trvá $\O(S~+ \vert V \vert)$. Celé hledání tedy trvá lineárnì v~délce vstupu a~výstupu. Zbývá nám u¾ jen konstrukce automatu. Opìt vyu¾ijeme faktu, ¾e zpìtná hrana ze stavu $\beta$ vede tam, kam by se dostal automat pøi hledání $\beta$ bez prvního písmenka. Tak¾e zase chceme nìco, jako simulovat výpoèet toho automatu na~slovech bez prvního písmenka a~doufat v~to, ¾e si vystaèíme s~tou èástí automatu, kterou jsme u¾ postavili. Tentokrát to v¹ak nemù¾eme dìlat jedno slovo po~druhém, proto¾e zpìtné hrany mohou vést køí¾em mezi jednotlivými vìtvemi automatu. Mohlo by se nám tedy stát, ¾e pøi hledání nìjakého slova potøebujeme zpìtnou hranu, která vede do~jiného slova, které jsme je¹tì nezkonstruovali. Tak¾e tento postup sel¾e. Mù¾eme v¹ak vyu¾ít toho, ¾e ka¾dá zpìtná hrana vede ve~stromu alespoò o~jednu hladinu vý¹. Mù¾eme tak strom konstruovat po~hladinách. Lze si to tedy pøedstavit tak, ¾e paralelnì spustíme vyhledávání v¹ech slov bez prvních písmenek a~v¾dycky udìláme jeden podkrok ka¾dého z~tìch hledání, co¾ nám dá zpìtné hrany z~dal¹ího patra stromu. diff --git a/7-geom/7-geom.tex b/7-geom/7-geom.tex index 87e9471..d600d11 100644 --- a/7-geom/7-geom.tex +++ b/7-geom/7-geom.tex @@ -2,7 +2,7 @@ \prednaska{7}{Geometrické algoritmy}{(sepsal Pavel Klavík)} -\>Uká¾eme si nìkolik základních algoritmù na øe¹ení geometrický problémù v~rovinì. Proè zrovna v~rovinì? Inu, jednorozmìrné problémy bývají triviální +\>Uká¾eme si nìkolik základních algoritmù na øe¹ení geometrických problémù v~rovinì. Proè zrovna v~rovinì? Inu, jednorozmìrné problémy bývají triviální a naopak pro vy¹¹í dimenze jsou velice komplikované. Rovina je proto rozumným kompromisem mezi obtí¾ností a zajímavostí. Celou kapitolou nás bude provázet pohádka ze ¾ivota ledních medvìdù. Pokusíme se vyøe¹it jejich \uv{ka¾dodenní} problémy~\dots @@ -110,7 +110,7 @@ z polorovin.} Algoritmu se øíká {\I provázkový}, proto¾e svojí èinností pøipomíná namotávání provázku podél konvexního obalu. Zaèneme s bodem, který na konvexním obalu urèitì le¾í, to je tøeba ten nejlevìj¹í. V ka¾dém kroku nalezneme následující bod po obvodu konvexního obalu. To udìláme napøíklad tak, ¾e projdeme v¹echny body a vybereme ten, který svírá nejmen¹í úhel s poslední stranou konvexního obalu. Novì pøidaná úseèka vyhovuje pozorování a proto -do konvexního obalu patøí. Po $h$ krocích dostaneme zpìt k nejlevìj¹ímu bodu a výpoèet ukonèíme. V ka¾dém kroku potøebujeme projít v¹echny body a +do konvexního obalu patøí. Po $h$ krocích se dostaneme zpìt k nejlevìj¹ímu bodu a výpoèet ukonèíme. V ka¾dém kroku potøebujeme projít v¹echny body a vybrat následníka, co¾ doká¾eme v èase $\O(n)$. Celková slo¾itost algoritmu je tedy $\O(n \cdot h)$. \twofigures{7-geom6_provazkovy_algoritmus.eps}{Provázkový algoritmus.}{1.25in}{7-geom7_naslednik_pres_konvexni_obal.eps}{Hledání kandidáta v pøedpoèítaném obalu.}{2.5in} diff --git a/8-geom2/8-geom2.tex b/8-geom2/8-geom2.tex index a7f765f..034b395 100644 --- a/8-geom2/8-geom2.tex +++ b/8-geom2/8-geom2.tex @@ -6,7 +6,7 @@ V této pøedná¹ce nás spolu s dvìma geometrickými problémy samozøejmì èeká pokraèování pohádky o ledních medvìdech. {\I Medvìdi vyøe¹ili rybí problém a hlad je ji¾ netrápí. Av¹ak na severu ne¾ijí sami, za sousedy mají Eskymáky. Proto¾e je rozhodnì lep¹í se sousedy -dobøe vycházet, jsou medvìdi a Eskymáci velcí pøátelé. Skoro ka¾dý se svými pøáteli rád schází. Av¹ak to je musí nejprve nalézt~\dots} +dobøe vycházet, jsou medvìdi a Eskymáci velcí pøátelé. Skoro ka¾dý se se svými pøáteli rád schází. Av¹ak to je musí nejprve nalézt~\dots} \h{Hledání prùseèíkù úseèek} @@ -97,7 +97,7 @@ line programu v polynomiálním èase, byla pozitivnì vyøe¹ena -- je znám polynomiální algoritmus, kterému se øíká {\I metoda vnitøního bodu}. Na druhou stranu, pokud chceme najít pøípustné celoèíselné øe¹ení, je úloha NP-úplná a je jednoduché na ni pøevést spoustu optimalizaèních problémù. Dokázat NP-tì¾kost není pøíli¹ tì¾ké. Na druhou stranu ukázat, ¾e tento problém le¾í v NP, není vùbec jednoduché.} -Pøíklad Voroného diagram je naznaèen na obrázku. Zadané body jsou oznaèeny prázdnými krou¾ky a hranice oblastí $B_i$ jsou vyznaèené èernými èárami. +Pøíklad Voroného diagramu je naznaèen na obrázku. Zadané body jsou oznaèeny prázdnými krou¾ky a hranice oblastí $B_i$ jsou vyznaèené èernými èárami. \twofigures{8-geom2_2_polorovina.eps}{Body bli¾¹í k $a$ ne¾ $b$.}{1.25in}{8-geom2_3_voroneho_diagram.eps}{Voroného diagram.}{2.5in} @@ -130,8 +130,8 @@ intervalu v pr \log n)$ na dotaz, co¾ je hroznì pomalé. Pøedzpracování bude fungovat následovnì. Jak je naznaèeno na obrázku pøeru¹ovanými èárami, rozøe¾eme si celou rovinu na pásy, bìhem kterých se prùøez -pøímkou nemìní. Pro ka¾dý z nich pamatujeme stav stromu popisující, jak vypadal prùøez pøi procházení tímto pásem. Kdy¾ chceme lokalizovat nìjaký bod, -nejprve pùlením nalezneme pás, v kterém se nachází. Poté polo¾íme dotaz na pøíslu¹ný strom. Strom procházíme a po cestì si dopoèítáme souøadnice +pøímkou nemìní. Pro ka¾dý z nich si pamatujeme stav stromu popisující, jak vypadal prùøez pøi procházení tímto pásem. Kdy¾ chceme lokalizovat nìjaký bod, +nejprve pùlením nalezneme pás, ve kterém se nachází. Poté polo¾íme dotaz na pøíslu¹ný strom. Strom procházíme a po cestì si dopoèítáme souøadnice prùøezu, a¾ lokalizujeme správný interval v prùøezu. Dotaz doká¾eme zodpovìdìt v èase $\O(\log n)$. Hledaný bod je na obrázku naznaèen prázdným koleèkem a nalezený interval v prùøezu je vyta¾ený tuènì.