% !TeX spellcheck = cs_CZ
% !TeX root = ../BP_Prokopič_Martin_2021.tex

Existuje 39~916~800 permutací slova \texttt{mississippi}. Jedna z~nich, \texttt{pssmipissii}, je ale výjimečná tím, že jde o~jedinou existující Burrows-Wheelerovu transformaci řetězce \texttt{mississippi}. Navíc neexistuje žádné další slovo, jehož transformací by vznikl stejný výstup. Zároveň známe rychlý způsob, jak provést obrácenou transformaci a~z~výstupu získat zpět původní řetězec.

\acrshort{bwt} poprvé publikovali Michael Burrows a~David Wheeler v~roce 1994 \cite{burrows94} a~od té doby nalézá široké uplatnění hlavně v~oblasti komprese dat, kde představuje jednu z~nejefektivnějších dnes známých metod. Její implementaci můžeme potkat např. v~archivačním programu \texttt{bzip2} nebo se používá v~oboru bioinformatiky při analýze a~zarovnávání sekvencí DNA \cite{bell08}.

Výstup Burrows-Wheelerovy transformace obsahuje symboly seskupené podle kontextu ve vstupním řetězci. Často se v~něm tak nacházejí dlouhé úseky stejných nebo střídajících se symbolů. Takto permutované řetězce potom lze snáze komprimovat. V~prvním sloupci tabulky \ref{tab:symcontext} ukazujeme část výstupu transformace textu knihy \emph{Alice's Adventures in Wonderland} ze souboru Cantenbury Corpus \cite{bell02corpus}.

\begin{table}
	\centering
	\begin{tabular}{cc}
		výstup \acrshort{bwt} & kontext\\
		\hline
		\texttt{c} & \texttt{alled out to her in an a}\\
		\texttt{c} & \texttt{alled out, `First witnes}\\
		\texttt{c} & \texttt{alled out, `Sit down, al}\\
		\texttt{c} & \texttt{alled softly after it, `}\\
		\texttt{c} & \texttt{alled the Queen, who was}\\
		\texttt{f} & \texttt{allen by this time?' she}\\
		\texttt{f} & \texttt{allen into a~cucumber-fr}\\
		\texttt{f} & \texttt{allen into it:~~there we}\\
		\texttt{f} & \texttt{allen into the sea, `and}\\
		\texttt{t} & \texttt{aller and sometimes shor}
	\end{tabular}
	\caption{Ukázka vlivu kontextu na výstup BWT při transformaci souboru \texttt{alice29.txt} z~Cantenbury Corpus \cite{bell02corpus}}\label{tab:symcontext}
\end{table}

Pro ukázku možností komprese nyní výstup \acrshort{bwt} z~prvního sloupce tabulky \ref{tab:symcontext} zkomprimujeme jednoduchým algoritmem typu \textit{run-length encoding}, jehož podstatou je nahrazení vícenásobných repetic symbolů počtem opakování \cite{bell08}. Ukázkový výstup \texttt{cccccfffft} se tak může zkomprimovat například na \texttt{c5f4t1}, což je 60 \% délky původního řetězce. Reálná implementace tohoto algoritmu by dosáhla ještě lepšího poměru, ale to je již nad rámec této práce.
%Toto je velmi zjednodušené, reálná implementace by samozřejmě byla komplikovanější a~je nad rámec této práce.

Neméně zajímavou vlastností \acrshort{bwt} je, že zahrnutí informací o~kontextu symbolů do výstupu umožňuje v~původním řetězci vyhledávat v~sublineárním čase. Tato práce popisuje a~implementuje množinu vyhledávacích algoritmů, z~nichž některé díky využití zmíněných vztahů dosahují vysokého výkonu.

\section{Naivní algoritmy pro konstrukci \acrshort{bwt}}\label{sec:example}

Téma dopředné a~zpětné \acrshort{bwt} otevřeme představením naivních algoritmů pro její konstrukci. Na příkladu transformace řetězce \texttt{mississippi\$} ukážeme základní vztahy mezi vstupem a~výstupem \acrshort{bwt}, které potom v~sekci \ref{sec:improvements} využijeme ve vylepšených algoritmech, dostatečně rychlých pro použití v~praxi.

\subsection{Dopředná transformace}

Pro konstrukci Burrows-Wheelerovy transformace řetězce délky $n$ nad abecedou $\Sigma$ nejprve vypíšeme všechny jeho rotace do řádků matice $\mat{A} \in \Sigma^{n,n}$. To znamená, že opakovaně odebíráme poslední symbol slova a~přenášíme ho na jeho začátek, dokud se nedostaneme zpět k~původnímu slovu (v~našem případě \texttt{mississippi\$}). Tyto permutace poté lexikograficky seřadíme do matice $\mat{A}_s$ a~výsledek transformace přečteme v~jejím posledním sloupci.

Na konec řetězce jsme přidali ukončovací symbol \texttt{\$}, který je minimální ze všech symbolů abecedy $\Sigma$ a~nevyskytuje se jinde v~řetězci. Má to několik důvodů:
\begin{itemize}
	\item učiní to příklady přehlednějšími,
	\item je jasně určené, který řádek matice $\mat{A}_s$ obsahuje původní řetězec (nemusíme jeho index přenášet zvlášť s~výstupem BWT)
a~\item zajistíme, že matice $\mat{A}_s$ bude vždy odpovídat pořadí seřazených sufixů řetězce. Tento vztah bude později důležitý pro rychlé provedení dopředné transformace pomocí sufixového pole.
\end{itemize}

\begin{lrbox}{\boxa}
	\begin{minipage}{6.5em}
		\begin{verbatim}
		mississippi$
		ississippi$m
		ssissippi$mi
		sissippi$mis
		issippi$miss
		ssippi$missi
		sippi$missis
		ippi$mississ
		ppi$mississi
		pi$mississip
		i$mississipp
		$mississippi
		\end{verbatim}
	\end{minipage}
\end{lrbox}

\begin{lrbox}{\boxb}
	\begin{minipage}{6.5em}
		\begin{verbatim}
		$mississippi
		i$mississipp
		ippi$mississ
		issippi$miss
		ississippi$m
		mississippi$
		pi$mississip
		ppi$mississi
		sippi$missis
		sissippi$mis
		ssippi$missi
		ssissippi$mi
		\end{verbatim}
	\end{minipage}
\end{lrbox}

\begin{figure}
	\centering
	\subfloat[][]{\usebox{\boxa}\label{tab:bwtexample:a}}
	\qquad
	\subfloat[][]{\usebox{\boxb}\label{tab:bwtexample:as}}
	\qquad
	\subfloat[][]{\texttt{ipssm\$pissii}\label{tab:bwtexample:l}}\\
	\caption{Proces dopředné \acrshort{bwt} řetězce \texttt{mississippi\$}: \protect\subref{tab:bwtexample:a} matice $\mat{A}$; \protect\subref{tab:bwtexample:as} matice $\mat{A}_s$; \protect\subref{tab:bwtexample:l} výstup \acrshort{bwt} (poslední sloupec $\mat{A}_s$, pole $L$ ze sekce \ref{sec:bwimpl})}\label{tab:bwtexample}
\end{figure}

Pro seřazení permutací optimálním algoritmem potřebujeme $n\log n$ porovnání dvou řetězců, přičemž každé z~nich může trvat až $\BigO(n)$. Celkem tak popsaný naivní algoritmus pracuje v~čase $\BigO(n^2\log n)$ a~paměti $\BigO(n^2)$. \cite{bell08}

\subsection{Zpětná transformace}\label{sec:bwimpl}

Klíčovou vlastností pro praktickou využitelnost \acrshort{bwt} je existence rychlého (lineárního) algoritmu pro získání původního řetězce zpět z~výstupu. Označme $F$ první sloupec matice seřazených rotací $\mat{A}_s$ a~poslední ($n$-tý) $L$. Na vstup dekodéru dostáváme právě obsah sloupce $L$, a~snažíme se vypočítat původní řetězec $T$.

Můžeme si všimnout, že sloupec $F$ je pouze permutací sloupce $L$ -- obsahuje stejné symboly, akorát v~abecedním pořadí. Díky způsobu konstrukce matice $\mat{A}$ (rotace vstupního řetězce) platí, že po symbolech z~$L$ následují ve vstupu symboly z~$F$. Pokud bychom oba sloupce zapsali v~tomto pořadí vedle sebe, dostaneme všechny dvojice sousedních znaků z~původního řetězce, a~navíc dvojici poslední-první.

Seřazením těchto dvojic symbolů je možné získat sloupce $F$ a~$2$ matice $\mat{A}_s$. Uvažujeme-li původní řetězec jako cyklický (za posledním symbolem následuje opět první), tak opakovaným přidáváním známého sloupce $L$ a~řazením postupně získáváme podřetězce délky $2, 3, \ldots, n$. Po $n - 1$ opakováních takto zrekonstruujeme kompletní matici $\mat{A}_s$. Díky symbolu \texttt{\$} nyní snadno poznáme, který řádek obsahuje původní řetězec. Obrázek \ref{tab:decex} ilustruje dekódování slova \texttt{ipssm\$pissii}.

\begin{figure}
	\centering
%	\subfloat[][]{
%		\setlength\tabcolsep{0pt}
%		\begin{tabular}{c}
%			$L$\\
%			\hline
%			\texttt{i}\\
%			\texttt{p}\\
%			\texttt{s}\\
%			\texttt{s}\\
%			\texttt{m}\\
%			\texttt{\$}\\
%			\texttt{p}\\
%			\texttt{i}\\
%			\texttt{s}\\
%			\texttt{s}\\
%			\texttt{i}\\
%			\texttt{i}\\
%		\end{tabular}\label{tab:decex:l}
%	}
%	\quad
	\subfloat[][]{
		\setlength\tabcolsep{0pt}
		\begin{tabular}{cc}
			$F$ & ~\dots~\\
			\hline
			\texttt{\$} & \\
			\texttt{i} & \\
			\texttt{i} & \\
			\texttt{i} & \\
			\texttt{i} & \\
			\texttt{m} & \\
			\texttt{p} & \\
			\texttt{p} & \\
			\texttt{s} & \\
			\texttt{s} & \\
			\texttt{s} & \\
			\texttt{s} & \\
		\end{tabular}\label{tab:decex:f}
	}
	\quad
	\subfloat[][]{
		\setlength\tabcolsep{0pt}
		\begin{tabular}{ccc}
			$L$ & $F$ & ~\dots~\\
			\hline
			\texttt{i} & \texttt{\$} & \\
			\texttt{p} & \texttt{i} & \\
			\texttt{s} & \texttt{i} & \\
			\texttt{s} & \texttt{i} & \\
			\texttt{m} & \texttt{i} & \\
			\texttt{\$} & \texttt{m} & \\
			\texttt{p} & \texttt{p} & \\
			\texttt{i} & \texttt{p} & \\
			\texttt{s} & \texttt{s} & \\
			\texttt{s} & \texttt{s} & \\
			\texttt{i} & \texttt{s} & \\
			\texttt{i} & \texttt{s} & \\
		\end{tabular}\label{tab:decex:lf}
	}
	\quad
	\subfloat[][]{
		\setlength\tabcolsep{0pt}
		\begin{tabular}{ccc}
			$F$ & $2$ & ~\dots~\\
			\hline
			\texttt{\$} & \texttt{m} & \\
			\texttt{i} & \texttt{\$} & \\
			\texttt{i} & \texttt{p} & \\
			\texttt{i} & \texttt{s} & \\
			\texttt{i} & \texttt{s} & \\
			\texttt{m} & \texttt{i} & \\
			\texttt{p} & \texttt{i} & \\
			\texttt{p} & \texttt{p} & \\
			\texttt{s} & \texttt{i} & \\
			\texttt{s} & \texttt{i} & \\
			\texttt{s} & \texttt{s} & \\
			\texttt{s} & \texttt{s} & \\
		\end{tabular}\label{tab:decex:f2}
	}
	\quad
	\subfloat[][]{
		\setlength\tabcolsep{0pt}
		\begin{tabular}{cccc}
			$L$ & $F$ & $2$ & ~\dots~\\
			\hline
			\texttt{i} & \texttt{\$} & \texttt{m} & \\
			\texttt{p} & \texttt{i} & \texttt{\$} & \\
			\texttt{s} & \texttt{i} & \texttt{p} & \\
			\texttt{s} & \texttt{i} & \texttt{s} & \\
			\texttt{m} & \texttt{i} & \texttt{s} & \\
			\texttt{\$} & \texttt{m} & \texttt{i} & \\
			\texttt{p} & \texttt{p} & \texttt{i} & \\
			\texttt{i} & \texttt{p} & \texttt{p} & \\
			\texttt{s} & \texttt{s} & \texttt{i} & \\
			\texttt{s} & \texttt{s} & \texttt{i} & \\
			\texttt{i} & \texttt{s} & \texttt{s} & \\
			\texttt{i} & \texttt{s} & \texttt{s} & \\
		\end{tabular}\label{tab:decex:lf2}
	}
	\quad
	\subfloat[][]{
		\setlength\tabcolsep{0pt}
		\begin{tabular}{ccccc}
			$F$ & $2$ & $3$ & ~\dots~ & $L$\\
			\hline
			\texttt{\$} & \texttt{m} & \texttt{i} & & \texttt{i}\\
			\texttt{i} & \texttt{\$} & \texttt{m} & & \texttt{p}\\
			\texttt{i} & \texttt{p} & \texttt{p} & & \texttt{s}\\
			\texttt{i} & \texttt{s} & \texttt{s} & & \texttt{s}\\
			\texttt{i} & \texttt{s} & \texttt{s} & & \texttt{m}\\
			\texttt{m} & \texttt{i} & \texttt{s} & & \texttt{\$}\\
			\texttt{p} & \texttt{i} & \texttt{\$} & & \texttt{p}\\
			\texttt{p} & \texttt{p} & \texttt{i} & & \texttt{i}\\
			\texttt{s} & \texttt{i} & \texttt{p} & & \texttt{s}\\
			\texttt{s} & \texttt{i} & \texttt{s} & & \texttt{s}\\
			\texttt{s} & \texttt{s} & \texttt{i} & & \texttt{i}\\
			\texttt{s} & \texttt{s} & \texttt{i} & & \texttt{i}\\
		\end{tabular}\label{tab:decex:f23l}
	}
	\caption{Kroky při dekódování transformovaného řetězce \texttt{ipssm\$pissii}: \protect\subref{tab:decex:f} seřazený vstupní řetězec; \protect\subref{tab:decex:lf} před sloupec $F$ přidáme znova vstup $L$; \protect\subref{tab:decex:f2} opět seřadíme; \protect\subref{tab:decex:lf2} a~\protect\subref{tab:decex:f23l} opakujeme přidávání $L$ a~řazení, dokud nedekódujeme celou matici $\mat{A}_s$}\label{tab:decex}
\end{figure}

Tento algoritmus se v~popsané podobě praxi nepoužívá, protože při jeho běhu dochází k~$n$ řazením $n$ řádků délek postupně {1, \dots, $n$}, což dává celkovou časovou složitost $\BigO(n^3\log n)$, a~kvůli velikosti matice $\mat{A}_s$ paměťovou $\BigO(n^2)$. V~sekci \ref{sec:revimpl} popíšeme algoritmus, který dokáže provést zpětnou BWT v~lineárním čase a~paměti. \cite{bell08}

\section{Praktická implementace \acrshort{bwt}}\label{sec:improvements}

V~sekci \ref{sec:example} jsme popsali naivní algoritmy pro dopřednou a~zpětnou Burrows-Wheelerovu transformaci. Pro praktické využití jsou ale příliš pomalé a~paměťově náročné (ukládat matici rotací delších řetězců si v~reálných aplikacích nemůžeme dovolit). M. Burrows a~D. Wheeler v~\cite{burrows94} popsali efektivnější způsoby konstrukce dopředné a~zpětné transformace, a~ty představíme v~následujících podsekcích.

\subsection{Vylepšení dopředné transformace}\label{sec:fwimpl}

U~dopředné transformace můžeme snížit paměťovou náročnost z~$\BigO(n^2)$ na $\BigO(n)$ relativně jednoduchou úpravou algoritmu představeného dříve. Nechť $T[1\ldots n]$ je vstupní řetězec délky $n = |T|$.

Místo toho, abychom si pamatovali celou matici rotací $\mat{A}$, respektive $\mat{A}_s$ velikosti $n \times n$, zavedeme pomocné pole $I[1 \ldots n]$ obsahující na indexu $i$ informaci, na jaké pozici se nachází symbol $F[i]$ v~původním textu $T$. Pole $I$ inicializujeme hodnotami $1, \ldots, n$ (představují matici $\mat{A}$), a~poté seřadíme s~použitím porovnávací funkce \method{BWT-Strcmp} uvedené v~algoritmu \ref{algo:bwtstrcmp}. Simulujeme tak řazení řádků matice $\mat{A}_s$ bez toho, abychom ji drželi v~paměti.

\begin{algorithm}
\AlgoName{BWT-Strcmp}{$(T, i, j)$}
$m \leftarrow |T|$\;
\While{$m > 0$ \KwAnd $T[i] = T[j]$}{
	$i \leftarrow (i \bmod |T|) + 1$\;
	$j \leftarrow (j \bmod |T|) + 1$\;
	$m \leftarrow m - 1$\;
}
\eIf{$m = 0$}{
	\KwRet $0$\;
}{
	\KwRet $T[j] - T[i]$\;
}
\caption{Porovnávací funkce použitá pro řazení pole $I$}\label{algo:bwtstrcmp}
\end{algorithm}

Kdybychom po seřazení chtěli vypsat $i$-tý řádek matice $\mat{A}_s$, začneme od symbolu $T[I[i]]$ s~tím, že pokud narazíme na konec řetězce, tak se přesuneme na začátek. Výsledek \acrshort{bwt} čteme v~posledním sloupci $L$ matice $\mat{A}_s$, tedy díky přetečení rotací z~prvního na poslední sloupec platí pro každé $i = 1, \ldots, n$:
\begin{equation*}
	L[i] = \begin{cases}
T[I[i]-1]&\text{pokud } I[i] > 1\text{,}\\
T[n]&\text{jinak.}
	\end{cases}
\end{equation*}

\begin{example}
	Transformujeme řetězec $T = $ \texttt{mississippi\$}. Pole $I$ po seřazení vypadá následovně: $(12,11,8,5,2,1,10,9,7,4,6,3)$. První řádek matice $\mat{A}_s$ tak začíná symbolem \texttt{\$} (teď čteme dál od začátku $T$), a~pokračuje \texttt{mississippi}. Poslední symbol (tedy $L[1]$) můžeme rychle najít na $12-1 = 11$ pozici v~$T$. Obdobně $L[2] = T[11-1] = T[10] =$ \texttt{p}.
\end{example}

Tento algoritmus pracuje stále v~čase $\BigO(n^2\log n)$ (řadíme $n$ řetězců délky $n$), ale stačí mu pouze $\BigO(n)$ paměti pro pomocné pole $I$.

Pokud na konec vstupního řetězce přidáme ukončovací symbol \texttt{\$}, který se jinde v~$T$ nevyskytuje a~je menší než všechny ostatní symboly abecedy, převedeme problém dopředné \acrshort{bwt} na řazení sufixů $T$. Pole $I$ v~tom případě představuje \textit{sufixové pole} řetězce $T$ \cite{burrows94}. Existují algoritmy pro konstrukci sufixového pole v~čase $\BigO(n)$ \cite{manber90}, a~tím pádem je možné provést v~tomto čase celou transformaci.

\subsection{Praktický algoritmus pro zpětnou transformaci}\label{sec:revimpl}

I~pro zpětnou Burrows-Wheelerovu transformaci popsali autoři \cite{burrows94} algoritmus pracující v~lineárním čase a~paměti vůči $n$. Místo toho, abychom ukládali kompletní matici $\mat{A}_s$, zkonstruujeme pomocná pole, která umožní pohyb v~transformovaném výstupu $L$, jako kdyby se jednalo o~vstupní řetězec $T$.

Klíčové je pozorování, že pokud napíšeme obsah $L$ a~$F$ vedle sebe, dostaneme dvojice po sobě následujících symbolů v~původním řetězci $T$. Pole $F$ je navíc pouze $L$ seřazené v~abecedním pořadí. Dekódování si můžeme představit jako proces, při němž tyto dvojice poskládáme za sebe\footnote{Jako domino!} do řetězce $T$.

Díky tomu, že matice $\mat{A}_s$ vznikla seřazením \emph{rotací} řetězce $T$, $k$-tý výskyt symbolu $a$ ($a_k$) v~$L$ odpovídá $k$-tému výskytu $a$ v~$F$. Pokud $T[i] = a_k$ a~$a_k$ se v~$L$ nachází na indexu $j$, potom $T[i+1] = F[j]$. Postup v~dekódovacím algoritmu představeném v~\cite{burrows94} ale neumožňuje snadno zjistit $F[i]$ pro nějaké $i$, využívá proto vztahu pro dekódování předchůdce: $T[i-1] = L[j]$, kdy $T[i] = a_k = F[j]$.

\begin{example}
	Chceme řetězec $L =$ \texttt{ipssm\$pissii} dekódovat pozpátku. Pole $L$, $F$ a~původní řetězec $T$ jsme znázornili v~tabulce \ref{tab:flrel}. Víme, že musíme začít od ukončovacího symbolu $\texttt{\$}_1$, který je v~$L[6]$. Odpovídající symbol najdeme v~$F[1]$, předchozí znak $T[11]$ je tedy $L[1] = \texttt{i}_1$. Ten opět hledáme v~$F$ a~najdeme ho na indexu $F[2]$. Získali jsme tak další znak $T[10] = L[2] = \texttt{p}_1$. Tento postup opakujeme, dokud nedekódujeme poslední (první) symbol $T[1] = L[5] = \texttt{m}_1$.
\end{example}

Časová složitost popsaného algoritmu závisí na rychlosti nalezení $k$-tého výskytu symbolu $a$ v~poli $F$. Obecně se časová složitost bude pohybovat v~\mbox{$\BigO(n\cdot t)$}, kde $t$ je čas potřebný pro jedno hledání $a_k$ v~$F$.

\begin{table}
	\centering
	\begin{tabular}{rccc}
		$i$ & $L$ & $F$ & $T$\\
		\hline
		1 & $\texttt{i}_1$ & $\texttt{\$}_1$ & $\texttt{m}_1$\\
		2 & $\texttt{p}_1$ & $\texttt{i}_1$ & $\texttt{i}_4$\\
		3 & $\texttt{s}_1$ & $\texttt{i}_2$ & $\texttt{s}_4$\\
		4 & $\texttt{s}_2$ & $\texttt{i}_3$ & $\texttt{s}_2$\\
		5 & $\texttt{m}_1$ & $\texttt{i}_4$ & $\texttt{i}_3$\\
		6 & $\texttt{\$}_1$ & $\texttt{m}_1$ & $\texttt{s}_3$\\
		7 & $\texttt{p}_2$ & $\texttt{p}_1$ & $\texttt{s}_1$\\
		8 & $\texttt{i}_2$ & $\texttt{p}_2$ & $\texttt{i}_2$\\
		9 & $\texttt{s}_3$ & $\texttt{s}_1$ & $\texttt{p}_2$\\
		10 & $\texttt{s}_4$ & $\texttt{s}_2$ & $\texttt{p}_1$\\
		11 & $\texttt{i}_3$ & $\texttt{s}_3$ & $\texttt{i}_1$\\
		12 & $\texttt{i}_4$ & $\texttt{s}_4$ & $\texttt{\$}_1$\\
	\end{tabular}
	\caption{Znázornění vztahu relativního pořadí symbolů v~polích $F$, $L$ a~$T$}\label{tab:flrel}
\end{table}

\subsection{Datové struktury pro zpětnou transformaci}\label{sec:auxiliary}

Úspěch dekódovacího algoritmu v~předchozí sekci (\ref{sec:revimpl}) stojí a~padá na schopnosti rychle najít index $k$-tého výskytu symbolu $a$ v~poli $F$. Na vstupu ale máme pouze řetězec $L$ obsahující výstup \acrshort{bwt}.

Čtenář by mohl namítnout, že jen na samotné sestavení pole $F$ potřebujeme čas $\BigO(n\log n)$. Díky využití pomocných polí a~algoritmu podobnému \emph{counting sort} zvládneme operaci z~prvního odstavce provádět v~konstantním čase, a~tedy získat celkovou složitost dekódovaní $\BigO(n)$ \cite{burrows94}.

Označme $\Sigma$ abecedu řetězce $L$ a~zavedeme pole $K$ velikosti $|\Sigma|$. Do $K[i]$ uložíme počet symbolů $\sigma_i$ v~$L$ pro každé $i \in \set{1, \ldots, |\Sigma|}$. Dále zavedeme pole $M[1\dotdot |\Sigma|]$ jako prefixový součet $K$, to znamená, že $M[i] = 1 + \Sigma_{j=1}^{i-1}K[j]$.

Číslo $M[i]$ tak udává index prvního výskytu symbolu $\sigma_i$ v~$F$. Díky abecednímu pořadí jsou všechny výskyty v~souvislém intervalu. Ještě zbývá určit, který z~následujících $K[i]$ symbolů $\sigma_i$ odpovídá námi hledanému symbolu z~$L$. K~tomu slouží další pomocné pole $C[1\dotdot n]$.

To obsahuje na indexu $i$ počet symbolů $L[i]$ v~podřetězci $T[1\dotdot(i-1)]$. Dohromady pole $M$ a~$C$ určují, na které pozici v~$F$ se nachází odpovídající symbol z~$L$. Předchůdce $L[i]$ v~dekódovaném textu $T$ najdeme v~$L$ na indexu $C[i] + M[\symdex(L[i])]$, kde funkce $\symdex: \Sigma \rightarrow \mathbb{N}$ vrátí $i$ pro $\sigma_i$. Obsah těchto tří polí pro řetězec \texttt{mississippi\$} uvádíme v~tabulce \ref{tab:arrex}.

Zpětná transformace celého řetězce $L$ je jen otázkou opakování $n$ kroků skoku na předchozí symbol. Ucelený algoritmus pro konstrukci $M$, $C$, $K$ a~dekódování $T$ v~čase $\BigO(n)$ uvádíme ve výpisu \ref{algo:decode} (přebraný z~\cite{bell05}).

Někdy nám ale nevyhovuje dekódování $T$ pozpátku. Zároveň se může v~praktických implementacích hodit vyměnit vyšší spotřebu paměti za rychlejší dekódování. K~tomu zavedeme komplementární dvojici \emph{dekódovacích} polí velikosti $n$: $V$ a~$W$.

Platí, že $V[i] = C[i] + M[\symdex(L[i])]$ a~$W[V[i]] = i$. Pole $W$ je tedy inverze k~$V$: zatímco $V[i]$ říká, kde se nachází předchozí symbol od $L[i]$ v~$T$, $W[i]$ obsahuje pozici symbolu následujícího.

Zpětnou \acrshort{bwt} řetězce $T$ popředu pomocí pole $W$ lze formálně zapsat pro každé $i \in \set{1\dotdot n}$ jako
\begin{equation*}
	T[i] = L[W^{i}[index]],
\end{equation*}
kde $L[index] =$ \texttt{\$}
a~\begin{equation*}
	W^k[i] = \begin{cases}
i~& \text{pokud }k = 0,\\
W[W^{k-1}[i]] & \text{jinak.}
	\end{cases}
\end{equation*}

Metodu \method{Build-Transform-Arrays} pro konstrukci dekódovacích polí uvádíme v~algoritmu \ref{algo:buildtrans}. Upozorňujeme, že verze popsaná v~pseudokódu během svého vykonávání přepisuje pole $M$.

Jedno z~posledních dvou pomocných polí jsme již zmínili v~sekci \ref{sec:fwimpl}. Jedná se o~dvojici $I$ a~$Hr$, která propojuje symboly původního řetězce $T$ se seřazeným polem $F$. První z~nich, $I$, je zvláště zajímavé, protože se jedná o~sufixové pole řetězce $T$ \cite{burrows94}. $Hr$ je opět inverze k~poli $I$ a~využívá se k~dekódování $L$ zprostředka. Obě pole jsou vzhledem k~$F$ definována následovně:
\begin{equation*}
\forall i~\in \set{1, \dots, n}: T[I[i]] = F[i],~T[i] = F[Hr[i]].
\end{equation*}

Algoritmus \method{Build-Auxiliary-Arrays} uvádíme ve výpisu \ref{algo:buildaux}. Využívá pole $W$, ale cyklus lze jednoduše upravit do podoby jako je v~\method{BWT-Decode}. Zároveň v~tabulkách \ref{tab:arr} a~\ref{tab:arrex} uvádíme stručný přehled všech polí a~jejich hodnoty pro řetězec $T =$ \texttt{mississippi\$}.

\vspace{6pt}

\begin{table}[h]
	\centering
	\begin{tabular}{ccl}
		Značení & Vel. & Popis pole\\
		\hline\\[-1.1em]
		\multicolumn{3}{l}{\textbf{Hlavní pole}}\\
		\hline\\[-1em]
		$T$ & $n$ & Vstupní řetězec před transformací\\
		$F$ & $n$ & První sloupec $\mat{A}_s$; seřazené pole $T$\\
		$L$ & $n$ & Poslední sloupec matice $\mat{A}_s$; výstup BWT \vspace{4pt}\\
		\hline\\[-1.1em]
		\multicolumn{3}{l}{\textbf{Četnosti symbolů}}\\
		\hline\\[-1em]
		$K$ & $\abs{\Sigma}$ & $K[i] =$ počet symbolů $\sigma_i$ v~$L$\\
		$M$ & $\abs{\Sigma}$ & $M[i] =$ prefixová suma $K$; pozice prvního $\sigma_i$ v~$F$\\
		$C$ & $n$ & $C[i] =$ počet výskytů $L[i]$ v~$L[1\dotdot (i-1)]$ \vspace{4pt}\\
		\hline\\[-1.1em]
		\multicolumn{3}{l}{\textbf{Dekódovací pole}}\\
		\hline\\[-1em]
		$V$ & $n$ & zobrazení z~$L$ do $F$; slouží k~dekódování $T$ popředu\\
		$W$ & $n$ & inverze $V$; slouží k~dekódování $T$ pozpátku \vspace{4pt}\\
		\hline\\[-1.1em]
		\multicolumn{3}{l}{\textbf{Další pomocná pole}}\\
		\hline\\[-1em]
		$I$ & $n$ & zobrazení mezi $F$ a~$T$; sufixové pole $T$\\
		$Hr$ & $n$ & inverze $I$; slouží k~náhodnému dekódování textu\\
	\end{tabular}
	\caption{Přehled pomocných polí definovaných v~kapitole \ref{ch:bwt}}\label{tab:arr}
\end{table}

\begin{table}[h]
	\centering
	\subfloat[][]{
		\begin{tabular}{rccc}
			$i$ & $\sigma_i$ & $K$ & $M$\\
			\hline
			1 & \texttt{\$} & 1 & 1\\
			2 & \texttt{i} & 4 & 2\\
			3 & \texttt{m} & 1 & 6\\
			4 & \texttt{p} & 2 & 7\\
			5 & \texttt{s} & 4 & 9\\
		\end{tabular}
	}\label{tab:arrex:smol}
	\subfloat[][]{
		\begin{tabular}{rcccccccc}
			$i$ & $T$ & $F$ & $L$ & $C$ & $V$ & $W$ & $Hr$ & $I$\\
			\hline
			1 & \texttt{m} & \texttt{\$} & \texttt{i} & 0 & 2 & 6 & 6 & 12\\
			2 & \texttt{i} & \texttt{i} & \texttt{p} & 0 & 7 & 1 & 5 & 11\\
			3 & \texttt{s} & \texttt{i} & \texttt{s} & 0 & 9 & 8 & 12 & 8\\
			4 & \texttt{s} & \texttt{i} & \texttt{s} & 1 & 10 & 11 & 10 & 5\\
			5 & \texttt{i} & \texttt{i} & \texttt{m} & 0 & 6 & 12 & 4 & 2\\
			6 & \texttt{s} & \texttt{m} & \texttt{\$} & 0 & 1 & 5 & 11 & 1\\
			7 & \texttt{s} & \texttt{p} & \texttt{p} & 1 & 8 & 2 & 9 & 10\\
			8 & \texttt{i} & \texttt{p} & \texttt{i} & 1 & 3 & 7 & 3 & 9\\
			9 & \texttt{p} & \texttt{s} & \texttt{s} & 2 & 11 & 3 & 8 & 7\\
			10 & \texttt{p} & \texttt{s} & \texttt{s} & 3 & 12 & 4 & 7 & 4\\
			11 & \texttt{i} & \texttt{s} & \texttt{i} & 2 & 4 & 9 & 2 & 6\\
			12 & \texttt{\$} & \texttt{s} & \texttt{i} & 3 & 5 & 10 & 1 & 3\\
		\end{tabular}
	}\label{tab:arrex:big}
	\caption{Hodnoty všech pomocných polí pro řetězec \texttt{mississippi\$}}\label{tab:arrex}
\end{table}

\begin{algorithm}
\AlgoName{BWT-Decode}{$(L)$}
\For{$i \leftarrow 1$ \KwTo $|\Sigma|$}{
	$K[i] \leftarrow 0$\;
}
\BlankLine
\For{$i \leftarrow 1$ \KwTo $n$}{
	$C[i] \leftarrow K[\symdex(L[i])]$\;
	$K[\symdex(L[i])] \leftarrow K[\symdex(L[i])] + 1$\;
}
\BlankLine
$suma \leftarrow 1$\;
\For{$i \leftarrow 1$ \KwTo $|\Sigma|$}{
	$M[i] \leftarrow suma$\;
	$suma \leftarrow suma + K[i]$\;
}
\BlankLine
$i \leftarrow \text{index ukončovacího symbolu \texttt{\$} v~}L$\;
\For{$j \leftarrow n$ \KwTo $1$}{
	$T[j] \leftarrow L[i]$\;
	$i \leftarrow C[i] + M[\symdex(L[i])]$\;
}
\caption{Konstrukce polí $K$, $M$, $C$ a~dekódování řetězce $T$}\label{algo:decode}
\end{algorithm}

\begin{algorithm}
	\AlgoName{Build-Transform-Arrays}{$(L, M)$}
	\For{$i \leftarrow 1$ \KwTo $n$}{
		$V[i] \leftarrow M[\symdex(L[i])]$\;
		$W[M[\symdex(L[i])]] \leftarrow i$\;
		$M[\symdex(L[i])] \leftarrow M[\symdex(L[i])] + 1$\;
	}
	\caption{Konstrukce dvojice dekódovacích polí $V$ a~$W$}\label{algo:buildtrans}
\end{algorithm}

\begin{algorithm}
	\AlgoName{Build-Auxiliary-Arrays}{$(W)$}
	$i \leftarrow \text{index ukončovacího symbolu \texttt{\$} v~}L$\;
	\For{$j \leftarrow n$ \KwTo $1$}{
		$Hr[j] \leftarrow i$\;
		$I[i] \leftarrow j$\;
		$i \leftarrow W[i]$\;
	}
	\caption{Konstrukce sufixového pole $I$ a~jeho inverze $Hr$}\label{algo:buildaux}
\end{algorithm}
