<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Evarand</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Evarand"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/Evarand"/>
		<updated>2026-08-03T23:04:12Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B0%D0%B7%D1%80%D0%B5%D0%B7_%D0%B2_%D0%BF%D0%BB%D0%B0%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D1%85_%D0%B3%D1%80%D0%B0%D1%84%D0%B0%D1%85&amp;diff=58932</id>
		<title>Разрез в планарных графах</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B0%D0%B7%D1%80%D0%B5%D0%B7_%D0%B2_%D0%BF%D0%BB%D0%B0%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D1%85_%D0%B3%D1%80%D0%B0%D1%84%D0%B0%D1%85&amp;diff=58932"/>
				<updated>2017-01-06T15:27:08Z</updated>
		
		<summary type="html">&lt;p&gt;Evarand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Особенности [[укладка графа на плоскости | планарных графов]] позволяют реализовать поиск [[разрез, лемма о потоке через разрез | минимального разреза]] в планарном графе с лучшей асимптотикой, чем в произвольном графе, где поиск минимального разреза требует поиска максимального потока, то есть работает за &amp;lt;math&amp;gt;O(V^2E)&amp;lt;/math&amp;gt;. Лучший известный алгоритм для планарных графов работает с асимптотикой &amp;lt;math&amp;gt;O(V\log V)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Алгоритм за O(n^2 log n)==&lt;br /&gt;
&lt;br /&gt;
===Идея алгоритма===&lt;br /&gt;
Рассмотрим граф &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;, [[двойственный граф планарного графа | двойственный]] данному графу &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt;. Рассмотрим кратчайший путь &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt; между вершинами &amp;lt;math&amp;gt;\xi^s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi^t&amp;lt;/math&amp;gt;, принадлежащими граням &amp;lt;math&amp;gt;\varphi_s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt;, соответствующим вершинам &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; в исходном графе. Определим &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левые и &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правые ребра, &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левые будут лежать &amp;quot;слева&amp;quot; по пути из &amp;lt;math&amp;gt;\xi^s&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\xi^t&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правые &amp;quot;справа&amp;quot;. Формальное определение будет дано в следующем разделе. Тогда минимальный цикл в &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;, ограничивающий &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt;, будет &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-циклом {{---}} циклом, содержащим ровно одно &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левое и одно &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правое ребро, причем &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левое ребро входит в вершину &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
[[Файл:Xi_cycles.png|600px|thumb|center|Кси-циклы]]&lt;br /&gt;
&lt;br /&gt;
Каждый такой цикл соответствует разрезу в &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt;. Тогда алгоритм можно записать так:&lt;br /&gt;
# Построим граф &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;, двойственный исходному графу &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt;&lt;br /&gt;
# Найдем кратчайший путь &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt; между вершинами &amp;lt;math&amp;gt;\xi^s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi^t&amp;lt;/math&amp;gt;&lt;br /&gt;
# Для каждой вершины &amp;lt;math&amp;gt;\xi_i\in\Pi&amp;lt;/math&amp;gt; найдем кратчайший &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-цикл&lt;br /&gt;
# Найдем среди этих циклов цикл минимальной длины и построим соответствующий ему разрез в &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Корректность и асимптотика===&lt;br /&gt;
Рассмотрим неориентированный граф &amp;lt;math&amp;gt;G=(V, E)&amp;lt;/math&amp;gt;. Будем считать его трёхсвязным, если это не так, [[триангуляция полигонов (ушная + монотонная) | триангулируем]] его, используя ребра нулевой пропускной способности, это не изменит значение минимального &amp;lt;math&amp;gt;(s-t)-&amp;lt;/math&amp;gt; разреза. Минимальный разрез исходного графа будет состоять из ребер минимального разреза нового графа, которые есть и в исходном графе.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; трёхсвязен, поэтому существует единственный [[двойственный граф планарного графа | двойственный]] ему граф &amp;lt;math&amp;gt;G^d=(X, A)&amp;lt;/math&amp;gt;, при этом &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt; также трёхсвязен. Будем обозначать множество граней &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; как &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt;, множество граней &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt; как &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;. Между элементами каждой из пар множеств &amp;lt;math&amp;gt;V-\Phi&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;E-A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;F-X&amp;lt;/math&amp;gt; существует взаимно однозначное соответствие. Будем обозначать как &amp;lt;math&amp;gt;\alpha^d\in E&amp;lt;/math&amp;gt; элемент, соответствующий &amp;lt;math&amp;gt;\alpha\in A&amp;lt;/math&amp;gt;. Тогда длину ребра &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; определим как &amp;lt;math&amp;gt;l(\alpha)=c(\alpha^d)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем обозначать грани &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;, соответствующие вершинам &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt;, как &amp;lt;math&amp;gt;\varphi_s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt; соответственно. Далее будем считать, что &amp;lt;math&amp;gt;\varphi_s&amp;lt;/math&amp;gt; {{---}} внешняя грань &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; {{---}} минимальный &amp;lt;math&amp;gt;(s-t)-&amp;lt;/math&amp;gt; разрез, тогда &amp;lt;math&amp;gt;C^d=\{\alpha \mid \alpha^d\in C\}&amp;lt;/math&amp;gt; {{---}} цикл минимальной длины, ограничивающий &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
Формальное доказательство леммы громоздкое и здесь приведено не будет, однако сама лемма достаточно интуитивно понятна.&amp;lt;ref&amp;gt;&amp;quot;The following lemma is intuitive; however its formal proof is tedious, and therefore, omitted.&amp;quot;, Maximum flow in planar networks, Itai &amp;amp; Shiloach, 1979, p. 147&amp;lt;/ref&amp;gt; &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\xi^s\in\varphi_s&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\xi^t\in\varphi_t&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\Pi=(\xi^s=\xi_1, \ldots, \xi_k=\xi^t)&amp;lt;/math&amp;gt; {{---}} кратчайший путь между &amp;lt;math&amp;gt;\xi^s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi^t&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\alpha_i&amp;lt;/math&amp;gt; {{---}} ребро между &amp;lt;math&amp;gt;\xi_{i-1}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; для &amp;lt;math&amp;gt;i=2,\ldots,k&amp;lt;/math&amp;gt;. Будем называть ребро &amp;lt;math&amp;gt;\xi-\xi_i\in A&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левым, если оно находится между &amp;lt;math&amp;gt;\alpha_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\alpha_{i+1}&amp;lt;/math&amp;gt; при обходе ребер, входящих в  &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;, по часовой стрелке от &amp;lt;math&amp;gt;\alpha_i&amp;lt;/math&amp;gt;, и &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правым, если оно находится между &amp;lt;math&amp;gt;\alpha_{i+1}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\alpha_i&amp;lt;/math&amp;gt;.&lt;br /&gt;
Для того, чтобы это определение имело смысл для первой и последней вершин пути, можно добавить две вершины &amp;lt;math&amp;gt;\xi_0&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi_{k+1}&amp;lt;/math&amp;gt; и два ребра &amp;lt;math&amp;gt;\alpha_1=\xi_0-\xi_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\alpha_{k+1}=\xi_k-\xi_{k+1}&amp;lt;/math&amp;gt;. Важно, что никакое ребро не является одновременно &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левым и &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правым.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Виды_ребер.png|600px|thumb|center|П-левые и П-правые ребра]]&lt;br /&gt;
&lt;br /&gt;
Будем называть &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-циклом простой цикл, который содержит ровно одно &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левое и одно &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правое ребро, при этом &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левое ребро входит в вершину &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;. Любой &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-цикл ограничивает &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; {{---}} кратчайший ограничивающий &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt; цикл. Тогда существует &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-цикл такой же длины.&lt;br /&gt;
|proof=&lt;br /&gt;
&amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt; {{---}} кратчайший путь между &amp;lt;math&amp;gt;\xi^s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi^t&amp;lt;/math&amp;gt;, поэтому любой содержащийся в &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt; путь между &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi_j&amp;lt;/math&amp;gt; также кратчайший. При этом любой ограничиващий &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt; цикл обязан пересекать &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;. Цикл, не являющийся &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-циклом, не будет кратчайшим, так как его можно будет сократить вдоль пути &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Для поиска минимального &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-цикла построим из неориентированного графа &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; ориентированный граф &amp;lt;math&amp;gt;\vec{G}^d&amp;lt;/math&amp;gt; следующим образом: все &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левые ребра ориентируем из вершин &amp;lt;math&amp;gt;\xi\in\Pi&amp;lt;/math&amp;gt;, все &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правые ребра ориентируем в вершины &amp;lt;math&amp;gt;\xi\in\Pi&amp;lt;/math&amp;gt;, а остальные ребра &amp;lt;math&amp;gt;u\leftrightarrow v&amp;lt;/math&amp;gt; заменим на два ребра &amp;lt;math&amp;gt;u\rightarrow v&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;v\rightarrow u&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\xi_i\in\Pi&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;P_i&amp;lt;/math&amp;gt; {{---}} кратчайший нетривиальный путь из &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\vec{G}^d&amp;lt;/math&amp;gt;. Тогда соответствующий путь в &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt; является кратчайшим &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-циклом.&lt;br /&gt;
|proof=&lt;br /&gt;
Из определения &amp;lt;math&amp;gt;\vec{G}^d&amp;lt;/math&amp;gt; следует, что если нетривиальный путь из &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; содержит больше одного &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правого или &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левого ребра, то в нем есть самопересечение, то есть он не является простым, следовательно, не является кратчайшим &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-циклом.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Таким образом, нахождение минимального &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-цикла эквивалентно нахождению кратчайшего нетривиального пути из &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\vec{G}^d&amp;lt;/math&amp;gt;. Это можно сделать за &amp;lt;math&amp;gt;O(m\log n)&amp;lt;/math&amp;gt;, например, с помощью [[алгоритм Дейкстры | алгоритма Дейкстры]]. Так как в планарных графах &amp;lt;math&amp;gt;m=O(n)&amp;lt;/math&amp;gt;, это равно &amp;lt;math&amp;gt;O(n\log n)&amp;lt;/math&amp;gt;. Максимум &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; таких поисков дадут итоговую асимптотику &amp;lt;math&amp;gt;O(n^2\log n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Двойственный граф планарного графа]]&lt;br /&gt;
* [[Разрез, лемма о потоке через разрез]]&lt;br /&gt;
* [[Укладка графа на плоскости]]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [http://verona.dei.unipd.it/~prin08/primo_meeting/italiano.pdf Improved Algorithms for Min Cuts and Max Flows in Undirected Planar Graphs]&lt;br /&gt;
* [https://pdfs.semanticscholar.org/b838/35db99723f922b7b286d10952b08c68970a7.pdf Maximum flow in planar networks, Itai &amp;amp; Shiloach, 1979]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Укладки графов]]&lt;/div&gt;</summary>
		<author><name>Evarand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Xi_cycles.png&amp;diff=58931</id>
		<title>Файл:Xi cycles.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Xi_cycles.png&amp;diff=58931"/>
				<updated>2017-01-06T15:21:37Z</updated>
		
		<summary type="html">&lt;p&gt;Evarand: загружена новая версия «Файл:Xi cycles.png»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Кси-циклы, алгоритм поиска разреза в планарном графе&lt;/div&gt;</summary>
		<author><name>Evarand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%92%D0%B8%D0%B4%D1%8B_%D1%80%D0%B5%D0%B1%D0%B5%D1%80.png&amp;diff=58930</id>
		<title>Файл:Виды ребер.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%92%D0%B8%D0%B4%D1%8B_%D1%80%D0%B5%D0%B1%D0%B5%D1%80.png&amp;diff=58930"/>
				<updated>2017-01-06T15:19:45Z</updated>
		
		<summary type="html">&lt;p&gt;Evarand: загружена новая версия «Файл:Виды ребер.png»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;П-левые и П-правые ребра, алгоритм поиска разреза в планарном графе&lt;/div&gt;</summary>
		<author><name>Evarand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B0%D0%B7%D1%80%D0%B5%D0%B7_%D0%B2_%D0%BF%D0%BB%D0%B0%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D1%85_%D0%B3%D1%80%D0%B0%D1%84%D0%B0%D1%85&amp;diff=58883</id>
		<title>Разрез в планарных графах</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B0%D0%B7%D1%80%D0%B5%D0%B7_%D0%B2_%D0%BF%D0%BB%D0%B0%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D1%85_%D0%B3%D1%80%D0%B0%D1%84%D0%B0%D1%85&amp;diff=58883"/>
				<updated>2017-01-05T21:30:55Z</updated>
		
		<summary type="html">&lt;p&gt;Evarand: /* Корректность и асимптотика */ minor&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Особенности [[укладка графа на плоскости | планарных графов]] позволяют реализовать поиск [[разрез, лемма о потоке через разрез | минимального разреза]] в планарном графе с лучшей асимптотикой, чем в произвольном графе, где поиск минимального разреза требует поиска максимального потока, то есть работает за &amp;lt;math&amp;gt;O(V^2E)&amp;lt;/math&amp;gt;. Лучший известный алгоритм для планарных графов работает с асимптотикой &amp;lt;math&amp;gt;O(V\log V)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Алгоритм за &amp;lt;math&amp;gt;O(n^2 \log n)&amp;lt;/math&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
===Идея алгоритма===&lt;br /&gt;
Рассмотрим граф &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;, [[двойственный граф планарного графа | двойственный]] данному графу &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt;. Рассмотрим кратчайший путь &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt; между вершинами &amp;lt;math&amp;gt;\xi^s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi^t&amp;lt;/math&amp;gt;, принадлежащими граням &amp;lt;math&amp;gt;\varphi_s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt;, соответствующим вершинам &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; в исходном графе. Определим &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левые и &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правые ребра, &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левые будут лежать &amp;quot;слева&amp;quot; по пути из &amp;lt;math&amp;gt;\xi^s&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\xi^t&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правые &amp;quot;справа&amp;quot;. Формальное определение будет дано в следующем разделе. Тогда минимальный цикл в &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;, ограничивающий &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt;, будет &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-циклом {{---}} циклом, содержащим ровно одно &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левое и одно &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правое ребро, причем &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левое ребро входит в вершину &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
[[Файл:Xi_cycles.png|600px|thumb|center|Кси-циклы]]&lt;br /&gt;
&lt;br /&gt;
Каждый такой цикл соответствует разрезу в &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt;. Тогда алгоритм можно записать так:&lt;br /&gt;
# Построим граф &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;, двойственный исходному графу &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt;&lt;br /&gt;
# Найдем кратчайший путь &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt; между вершинами &amp;lt;math&amp;gt;\xi^s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi^t&amp;lt;/math&amp;gt;&lt;br /&gt;
# Для каждой вершины &amp;lt;math&amp;gt;\xi_i\in\Pi&amp;lt;/math&amp;gt; найдем кратчайший &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-цикл&lt;br /&gt;
# Найдем среди этих циклов цикл минимальной длины и построим соответствующий ему разрез в &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Корректность и асимптотика===&lt;br /&gt;
Рассмотрим неориентированный граф &amp;lt;math&amp;gt;G=(V, E)&amp;lt;/math&amp;gt;. Будем считать его трёхсвязным, если это не так, [[триангуляция полигонов (ушная + монотонная) | триангулируем]] его, используя ребра нулевой пропускной способности, это не изменит значение минимального &amp;lt;math&amp;gt;(s-t)-&amp;lt;/math&amp;gt; разреза. Минимальный разрез исходного графа будет состоять из ребер минимального разреза нового графа, которые есть и в исходном графе.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; трёхсвязен, поэтому существует единственный [[двойственный граф планарного графа | двойственный]] ему граф &amp;lt;math&amp;gt;G^d=(X, A)&amp;lt;/math&amp;gt;, при этом &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt; также трёхсвязен. Будем обозначать множество граней &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; как &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt;, множество граней &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt; как &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;. Между элементами каждой из пар множеств &amp;lt;math&amp;gt;V-\Phi&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;E-A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;F-X&amp;lt;/math&amp;gt; существует взаимно однозначное соответствие. Будем обозначать как &amp;lt;math&amp;gt;\alpha^d\in E&amp;lt;/math&amp;gt; элемент, соответствующий &amp;lt;math&amp;gt;\alpha\in A&amp;lt;/math&amp;gt;. Тогда длину ребра &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; определим как &amp;lt;math&amp;gt;l(\alpha)=c(\alpha^d)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем обозначать грани &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;, соответствующие вершинам &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt;, как &amp;lt;math&amp;gt;\varphi_s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt; соответственно. Далее будем считать, что &amp;lt;math&amp;gt;\varphi_s&amp;lt;/math&amp;gt; {{---}} внешняя грань &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; {{---}} минимальный &amp;lt;math&amp;gt;(s-t)-&amp;lt;/math&amp;gt; разрез, тогда &amp;lt;math&amp;gt;C^d=\{\alpha \mid \alpha^d\in C\}&amp;lt;/math&amp;gt; {{---}} цикл минимальной длины, ограничивающий &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt;. &lt;br /&gt;
Формальное доказательство леммы громоздкое и здесь приведено не будет, однако сама лемма достаточно интуитивно понятна.&amp;lt;ref&amp;gt;&amp;quot;The following lemma is intuitive; however its formal proof is tedious, and therefore, omitted.&amp;quot;, Maximum flow in planar networks, Itai &amp;amp; Shiloach, 1979, p. 147&amp;lt;/ref&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\xi^s\in\varphi_s&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\xi^t\in\varphi_t&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\Pi=(\xi^s=\xi_1, \ldots, \xi_k=\xi^t)&amp;lt;/math&amp;gt; {{---}} кратчайший путь между &amp;lt;math&amp;gt;\xi^s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi^t&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\alpha_i&amp;lt;/math&amp;gt; {{---}} ребро между &amp;lt;math&amp;gt;\xi_{i-1}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; для &amp;lt;math&amp;gt;i=2,\ldots,k&amp;lt;/math&amp;gt;. Будем называть ребро &amp;lt;math&amp;gt;\xi-\xi_i\in A&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левым, если оно находится между &amp;lt;math&amp;gt;\alpha_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\alpha_{i+1}&amp;lt;/math&amp;gt; при обходе ребер, входящих в  &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;, по часовой стрелке от &amp;lt;math&amp;gt;\alpha_i&amp;lt;/math&amp;gt;, и &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правым, если оно находится между &amp;lt;math&amp;gt;\alpha_{i+1}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\alpha_i&amp;lt;/math&amp;gt;.&lt;br /&gt;
Для того, чтобы это определение имело смысл для первой и последней вершин пути, можно добавить две вершины &amp;lt;math&amp;gt;\xi_0&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi_{k+1}&amp;lt;/math&amp;gt; и два ребра &amp;lt;math&amp;gt;\alpha_1=\xi_0-\xi_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\alpha_{k+1}=\xi_k-\xi_{k+1}&amp;lt;/math&amp;gt;. Важно, что никакое ребро не является одновременно &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левым и &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правым.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Виды_ребер.png|600px|thumb|center|П-левые и П-правые ребра]]&lt;br /&gt;
&lt;br /&gt;
Будем называть &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-циклом простой цикл, который содержит ровно одно &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левое и одно &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правое ребро, при этом &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левое ребро входит в вершину &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;. Любой &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-цикл ограничивает &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; {{---}} кратчайший ограничивающий &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt; цикл. Тогда существует &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-цикл такой же длины.&lt;br /&gt;
|proof=&lt;br /&gt;
&amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt; {{---}} кратчайший путь между &amp;lt;math&amp;gt;\xi^s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi^t&amp;lt;/math&amp;gt;, поэтому любой содержащийся в &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt; путь между &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi_j&amp;lt;/math&amp;gt; также кратчайший. При этом любой ограничиващий &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt; цикл обязан пересекать &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;. Цикл, не являющийся &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-циклом, не будет кратчайшим, так как его можно будет сократить вдоль пути &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Для поиска минимального &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-цикла построим из неориентированного графа &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; ориентированный граф &amp;lt;math&amp;gt;\vec{G}^d&amp;lt;/math&amp;gt; следующим образом: все &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левые ребра ориентируем из вершин &amp;lt;math&amp;gt;\xi\in\Pi&amp;lt;/math&amp;gt;, все &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правые ребра ориентируем в вершины &amp;lt;math&amp;gt;\xi\in\Pi&amp;lt;/math&amp;gt;, а остальные ребра &amp;lt;math&amp;gt;u\leftrightarrow v&amp;lt;/math&amp;gt; заменим на два ребра &amp;lt;math&amp;gt;u\rightarrow v&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;v\rightarrow u&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\xi_i\in\Pi&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;P_i&amp;lt;/math&amp;gt; {{---}} кратчайший нетривиальный путь из &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\vec{G}^d&amp;lt;/math&amp;gt;. Тогда соответствующий путь в &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt; является кратчайшим &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-циклом.&lt;br /&gt;
|proof=&lt;br /&gt;
Из определения &amp;lt;math&amp;gt;\vec{G}^d&amp;lt;/math&amp;gt; следует, что если нетривиальный путь из &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; содержит больше одного &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правого или &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левого ребра, то в нем есть самопересечение, то есть он не является простым, следовательно, не является кратчайшим &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-циклом.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Таким образом, нахождение минимального &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-цикла эквивалентно нахождению кратчайшего нетривиального пути из &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\vec{G}^d&amp;lt;/math&amp;gt;. Это можно сделать за &amp;lt;math&amp;gt;O(m\log n)&amp;lt;/math&amp;gt;, например, с помощью [[алгоритм Дейкстры | алгоритма Дейкстры]]. Так как в планарных графах &amp;lt;math&amp;gt;m=O(n)&amp;lt;/math&amp;gt;, это равно &amp;lt;math&amp;gt;O(n\log n)&amp;lt;/math&amp;gt;. Максимум &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; таких поисков дадут итоговую асимптотику &amp;lt;math&amp;gt;O(n^2\log n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Двойственный граф планарного графа]]&lt;br /&gt;
* [[Разрез, лемма о потоке через разрез]]&lt;br /&gt;
* [[Укладка графа на плоскости]]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [http://verona.dei.unipd.it/~prin08/primo_meeting/italiano.pdf Improved Algorithms for Min Cuts and Max Flows in Undirected Planar Graphs]&lt;br /&gt;
* [https://pdfs.semanticscholar.org/b838/35db99723f922b7b286d10952b08c68970a7.pdf Maximum flow in planar networks, Itai &amp;amp; Shiloach, 1979]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Укладки графов]]&lt;/div&gt;</summary>
		<author><name>Evarand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B0%D0%B7%D1%80%D0%B5%D0%B7_%D0%B2_%D0%BF%D0%BB%D0%B0%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D1%85_%D0%B3%D1%80%D0%B0%D1%84%D0%B0%D1%85&amp;diff=58882</id>
		<title>Разрез в планарных графах</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B0%D0%B7%D1%80%D0%B5%D0%B7_%D0%B2_%D0%BF%D0%BB%D0%B0%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D1%85_%D0%B3%D1%80%D0%B0%D1%84%D0%B0%D1%85&amp;diff=58882"/>
				<updated>2017-01-05T21:28:46Z</updated>
		
		<summary type="html">&lt;p&gt;Evarand: /* Идея алгоритма */ minor&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Особенности [[укладка графа на плоскости | планарных графов]] позволяют реализовать поиск [[разрез, лемма о потоке через разрез | минимального разреза]] в планарном графе с лучшей асимптотикой, чем в произвольном графе, где поиск минимального разреза требует поиска максимального потока, то есть работает за &amp;lt;math&amp;gt;O(V^2E)&amp;lt;/math&amp;gt;. Лучший известный алгоритм для планарных графов работает с асимптотикой &amp;lt;math&amp;gt;O(V\log V)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Алгоритм за &amp;lt;math&amp;gt;O(n^2 \log n)&amp;lt;/math&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
===Идея алгоритма===&lt;br /&gt;
Рассмотрим граф &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;, [[двойственный граф планарного графа | двойственный]] данному графу &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt;. Рассмотрим кратчайший путь &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt; между вершинами &amp;lt;math&amp;gt;\xi^s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi^t&amp;lt;/math&amp;gt;, принадлежащими граням &amp;lt;math&amp;gt;\varphi_s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt;, соответствующим вершинам &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; в исходном графе. Определим &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левые и &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правые ребра, &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левые будут лежать &amp;quot;слева&amp;quot; по пути из &amp;lt;math&amp;gt;\xi^s&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\xi^t&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правые &amp;quot;справа&amp;quot;. Формальное определение будет дано в следующем разделе. Тогда минимальный цикл в &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;, ограничивающий &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt;, будет &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-циклом {{---}} циклом, содержащим ровно одно &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левое и одно &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правое ребро, причем &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левое ребро входит в вершину &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
[[Файл:Xi_cycles.png|600px|thumb|center|Кси-циклы]]&lt;br /&gt;
&lt;br /&gt;
Каждый такой цикл соответствует разрезу в &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt;. Тогда алгоритм можно записать так:&lt;br /&gt;
# Построим граф &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;, двойственный исходному графу &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt;&lt;br /&gt;
# Найдем кратчайший путь &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt; между вершинами &amp;lt;math&amp;gt;\xi^s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi^t&amp;lt;/math&amp;gt;&lt;br /&gt;
# Для каждой вершины &amp;lt;math&amp;gt;\xi_i\in\Pi&amp;lt;/math&amp;gt; найдем кратчайший &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-цикл&lt;br /&gt;
# Найдем среди этих циклов цикл минимальной длины и построим соответствующий ему разрез в &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Корректность и асимптотика===&lt;br /&gt;
Рассмотрим неориентированный граф &amp;lt;math&amp;gt;G=(V, E)&amp;lt;/math&amp;gt;. Будем считать его трёхсвязным, если это не так, [[триангуляция полигонов (ушная + монотонная) | триангулируем]] его, используя ребра нулевой пропускной способности, это не изменит значение минимального &amp;lt;math&amp;gt;(s-t)-&amp;lt;/math&amp;gt; разреза. Минимальный разрез исходного графа будет состоять из ребер минимального разреза нового графа, которые есть и в исходном графе.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; трёхсвязен, поэтому существует единственный [[двойственный граф планарного графа | двойственный]] ему граф &amp;lt;math&amp;gt;G^d=(X, A)&amp;lt;/math&amp;gt;, при этом &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt; также трёхсвязен. Будем обозначать множество граней &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; как &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt;, множество граней &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt; как &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;. Между элементами каждой из пар множеств &amp;lt;math&amp;gt;V-\Phi&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;E-A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;F-X&amp;lt;/math&amp;gt; существует взаимно однозначное соответствие. Будем обозначать как &amp;lt;math&amp;gt;\alpha^d\in E&amp;lt;/math&amp;gt; элемент, соответствующий &amp;lt;math&amp;gt;\alpha\in A&amp;lt;/math&amp;gt;. Тогда длину ребра &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; определим как &amp;lt;math&amp;gt;l(\alpha)=c(\alpha^d)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем обозначать грани &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;, соответствующие вершинам &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt;, как &amp;lt;math&amp;gt;\varphi_s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt; соответственно. Далее будем считать, что &amp;lt;math&amp;gt;\varphi_s&amp;lt;/math&amp;gt; {{---}} внешняя грань &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; {{---}} минимальный &amp;lt;math&amp;gt;(s-t)-&amp;lt;/math&amp;gt; разрез, тогда &amp;lt;math&amp;gt;C^d=\{\alpha \mid \alpha^d\in C\}&amp;lt;/math&amp;gt; {{---}} цикл минимальной длины, ограничивающий &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt;. &lt;br /&gt;
Формальное доказательство леммы громоздкое и здесь приведено не будет, однако сама лемма достаточно интуитивно понятна.&amp;lt;ref&amp;gt;&amp;quot;The following lemma is intuitive; however its formal proof is tedious, and therefore, omitted.&amp;quot;, Maximum flow in planar networks, Itai &amp;amp; Shiloach, 1979&amp;lt;/ref&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\xi^s\in\varphi_s&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\xi^t\in\varphi_t&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\Pi=(\xi^s=\xi_1, \ldots, \xi_k=\xi^t)&amp;lt;/math&amp;gt; {{---}} кратчайший путь между &amp;lt;math&amp;gt;\xi^s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi^t&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\alpha_i&amp;lt;/math&amp;gt; {{---}} ребро между &amp;lt;math&amp;gt;\xi_{i-1}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; для &amp;lt;math&amp;gt;i=2,\ldots,k&amp;lt;/math&amp;gt;. Будем называть ребро &amp;lt;math&amp;gt;\xi-\xi_i\in A&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левым, если оно находится между &amp;lt;math&amp;gt;\alpha_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\alpha_{i+1}&amp;lt;/math&amp;gt; при обходе ребер, входящих в  &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;, по часовой стрелке от &amp;lt;math&amp;gt;\alpha_i&amp;lt;/math&amp;gt;, и &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правым, если оно находится между &amp;lt;math&amp;gt;\alpha_{i+1}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\alpha_i&amp;lt;/math&amp;gt;.&lt;br /&gt;
Для того, чтобы это определение имело смысл для первой и последней вершин пути, можно добавить две вершины &amp;lt;math&amp;gt;\xi_0&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi_{k+1}&amp;lt;/math&amp;gt; и два ребра &amp;lt;math&amp;gt;\alpha_1=\xi_0-\xi_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\alpha_{k+1}=\xi_k-\xi_{k+1}&amp;lt;/math&amp;gt;. Важно, что никакое ребро не является одновременно &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левым и &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правым.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Виды_ребер.png|600px|thumb|center|П-левые и П-правые ребра]]&lt;br /&gt;
&lt;br /&gt;
Будем называть &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-циклом простой цикл, который содержит ровно одно &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левое и одно &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правое ребро, при этом &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левое ребро входит в вершину &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;. Любой &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-цикл ограничивает &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; {{---}} кратчайший ограничивающий &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt; цикл. Тогда существует &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-цикл такой же длины.&lt;br /&gt;
|proof=&lt;br /&gt;
&amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt; {{---}} кратчайший путь между &amp;lt;math&amp;gt;\xi^s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi^t&amp;lt;/math&amp;gt;, поэтому любой содержащийся в &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt; путь между &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi_j&amp;lt;/math&amp;gt; также кратчайший. При этом любой ограничиващий &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt; цикл обязан пересекать &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;. Цикл, не являющийся &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-циклом, не будет кратчайшим, так как его можно будет сократить вдоль пути &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Для поиска минимального &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-цикла построим из неориентированного графа &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; ориентированный граф &amp;lt;math&amp;gt;\vec{G}^d&amp;lt;/math&amp;gt; следующим образом: все &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левые ребра ориентируем из вершин &amp;lt;math&amp;gt;\xi\in\Pi&amp;lt;/math&amp;gt;, все &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правые ребра ориентируем в вершины &amp;lt;math&amp;gt;\xi\in\Pi&amp;lt;/math&amp;gt;, а остальные ребра &amp;lt;math&amp;gt;u\leftrightarrow v&amp;lt;/math&amp;gt; заменим на два ребра &amp;lt;math&amp;gt;u\rightarrow v&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;v\rightarrow u&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\xi_i\in\Pi&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;P_i&amp;lt;/math&amp;gt; {{---}} кратчайший нетривиальный путь из &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\vec{G}^d&amp;lt;/math&amp;gt;. Тогда соответствующий путь в &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt; является кратчайшим &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-циклом.&lt;br /&gt;
|proof=&lt;br /&gt;
Из определения &amp;lt;math&amp;gt;\vec{G}^d&amp;lt;/math&amp;gt; следует, что если нетривиальный путь из &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; содержит больше одного &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правого или &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левого ребра, то в нем есть самопересечение, то есть он не является простым, следовательно, не является кратчайшим &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-циклом.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Таким образом, нахождение минимального &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-цикла эквивалентно нахождению кратчайшего нетривиального пути из &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\vec{G}^d&amp;lt;/math&amp;gt;. Это можно сделать за &amp;lt;math&amp;gt;O(m\log n)&amp;lt;/math&amp;gt;, например, с помощью [[алгоритм Дейкстры | алгоритма Дейкстры]]. Так как в планарных графах &amp;lt;math&amp;gt;m=O(n)&amp;lt;/math&amp;gt;, это равно &amp;lt;math&amp;gt;O(n\log n)&amp;lt;/math&amp;gt;. Максимум &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; таких поисков дадут итоговую асимптотику &amp;lt;math&amp;gt;O(n^2\log n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Двойственный граф планарного графа]]&lt;br /&gt;
* [[Разрез, лемма о потоке через разрез]]&lt;br /&gt;
* [[Укладка графа на плоскости]]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [http://verona.dei.unipd.it/~prin08/primo_meeting/italiano.pdf Improved Algorithms for Min Cuts and Max Flows in Undirected Planar Graphs]&lt;br /&gt;
* [https://pdfs.semanticscholar.org/b838/35db99723f922b7b286d10952b08c68970a7.pdf Maximum flow in planar networks, Itai &amp;amp; Shiloach, 1979]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Укладки графов]]&lt;/div&gt;</summary>
		<author><name>Evarand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B0%D0%B7%D1%80%D0%B5%D0%B7_%D0%B2_%D0%BF%D0%BB%D0%B0%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D1%85_%D0%B3%D1%80%D0%B0%D1%84%D0%B0%D1%85&amp;diff=58881</id>
		<title>Разрез в планарных графах</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B0%D0%B7%D1%80%D0%B5%D0%B7_%D0%B2_%D0%BF%D0%BB%D0%B0%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D1%85_%D0%B3%D1%80%D0%B0%D1%84%D0%B0%D1%85&amp;diff=58881"/>
				<updated>2017-01-05T21:26:17Z</updated>
		
		<summary type="html">&lt;p&gt;Evarand: рефакторинг&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Особенности [[укладка графа на плоскости | планарных графов]] позволяют реализовать поиск [[разрез, лемма о потоке через разрез | минимального разреза]] в планарном графе с лучшей асимптотикой, чем в произвольном графе, где поиск минимального разреза требует поиска максимального потока, то есть работает за &amp;lt;math&amp;gt;O(V^2E)&amp;lt;/math&amp;gt;. Лучший известный алгоритм для планарных графов работает с асимптотикой &amp;lt;math&amp;gt;O(V\log V)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Алгоритм за &amp;lt;math&amp;gt;O(n^2 \log n)&amp;lt;/math&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
===Идея алгоритма===&lt;br /&gt;
Рассмотрим граф &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;, [[двойственный граф планарного графа | двойственный]] данному графу &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt;. Рассмотрим кратчайший путь &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt; между вершинами &amp;lt;math&amp;gt;\xi^s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi^t&amp;lt;/math&amp;gt;, принадлежащими граням &amp;lt;math&amp;gt;\varphi_s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt;, соответствующим вершинам &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; в исходном графе. Определим &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левые и &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правые ребра, &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левые будут лежать &amp;quot;слева&amp;quot; по пути из &amp;lt;math&amp;gt;\xi^s&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\xi^t&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-&amp;quot;правые&amp;quot; справа. Формальное определение будет дано в следующем разделе. Тогда минимальный цикл в &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;, ограничивающий &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt;, будет &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-циклом {{---}} циклом, содержащим ровно одно &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левое и одно &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правое ребро, причем &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левое ребро входит в вершину &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
[[Файл:Xi_cycles.png|600px|thumb|center|Кси-циклы]]&lt;br /&gt;
&lt;br /&gt;
Каждый такой цикл соответствует разрезу в &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt;. Тогда алгоритм можно записать так:&lt;br /&gt;
# Построим граф &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;, двойственный исходному графу &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt;&lt;br /&gt;
# Найдем кратчайший путь &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt; между вершинами &amp;lt;math&amp;gt;\xi^s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi^t&amp;lt;/math&amp;gt;&lt;br /&gt;
# Для каждой вершины &amp;lt;math&amp;gt;\xi_i\in\Pi&amp;lt;/math&amp;gt; найдем кратчайший &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-цикл&lt;br /&gt;
# Найдем среди этих циклов цикл минимальной длины и построим соответствующий ему разрез в &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Корректность и асимптотика===&lt;br /&gt;
Рассмотрим неориентированный граф &amp;lt;math&amp;gt;G=(V, E)&amp;lt;/math&amp;gt;. Будем считать его трёхсвязным, если это не так, [[триангуляция полигонов (ушная + монотонная) | триангулируем]] его, используя ребра нулевой пропускной способности, это не изменит значение минимального &amp;lt;math&amp;gt;(s-t)-&amp;lt;/math&amp;gt; разреза. Минимальный разрез исходного графа будет состоять из ребер минимального разреза нового графа, которые есть и в исходном графе.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; трёхсвязен, поэтому существует единственный [[двойственный граф планарного графа | двойственный]] ему граф &amp;lt;math&amp;gt;G^d=(X, A)&amp;lt;/math&amp;gt;, при этом &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt; также трёхсвязен. Будем обозначать множество граней &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; как &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt;, множество граней &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt; как &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;. Между элементами каждой из пар множеств &amp;lt;math&amp;gt;V-\Phi&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;E-A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;F-X&amp;lt;/math&amp;gt; существует взаимно однозначное соответствие. Будем обозначать как &amp;lt;math&amp;gt;\alpha^d\in E&amp;lt;/math&amp;gt; элемент, соответствующий &amp;lt;math&amp;gt;\alpha\in A&amp;lt;/math&amp;gt;. Тогда длину ребра &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; определим как &amp;lt;math&amp;gt;l(\alpha)=c(\alpha^d)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем обозначать грани &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;, соответствующие вершинам &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt;, как &amp;lt;math&amp;gt;\varphi_s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt; соответственно. Далее будем считать, что &amp;lt;math&amp;gt;\varphi_s&amp;lt;/math&amp;gt; {{---}} внешняя грань &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; {{---}} минимальный &amp;lt;math&amp;gt;(s-t)-&amp;lt;/math&amp;gt; разрез, тогда &amp;lt;math&amp;gt;C^d=\{\alpha \mid \alpha^d\in C\}&amp;lt;/math&amp;gt; {{---}} цикл минимальной длины, ограничивающий &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt;. &lt;br /&gt;
Формальное доказательство леммы громоздкое и здесь приведено не будет, однако сама лемма достаточно интуитивно понятна.&amp;lt;ref&amp;gt;&amp;quot;The following lemma is intuitive; however its formal proof is tedious, and therefore, omitted.&amp;quot;, Maximum flow in planar networks, Itai &amp;amp; Shiloach, 1979&amp;lt;/ref&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\xi^s\in\varphi_s&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\xi^t\in\varphi_t&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\Pi=(\xi^s=\xi_1, \ldots, \xi_k=\xi^t)&amp;lt;/math&amp;gt; {{---}} кратчайший путь между &amp;lt;math&amp;gt;\xi^s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi^t&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\alpha_i&amp;lt;/math&amp;gt; {{---}} ребро между &amp;lt;math&amp;gt;\xi_{i-1}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; для &amp;lt;math&amp;gt;i=2,\ldots,k&amp;lt;/math&amp;gt;. Будем называть ребро &amp;lt;math&amp;gt;\xi-\xi_i\in A&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левым, если оно находится между &amp;lt;math&amp;gt;\alpha_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\alpha_{i+1}&amp;lt;/math&amp;gt; при обходе ребер, входящих в  &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;, по часовой стрелке от &amp;lt;math&amp;gt;\alpha_i&amp;lt;/math&amp;gt;, и &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правым, если оно находится между &amp;lt;math&amp;gt;\alpha_{i+1}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\alpha_i&amp;lt;/math&amp;gt;.&lt;br /&gt;
Для того, чтобы это определение имело смысл для первой и последней вершин пути, можно добавить две вершины &amp;lt;math&amp;gt;\xi_0&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi_{k+1}&amp;lt;/math&amp;gt; и два ребра &amp;lt;math&amp;gt;\alpha_1=\xi_0-\xi_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\alpha_{k+1}=\xi_k-\xi_{k+1}&amp;lt;/math&amp;gt;. Важно, что никакое ребро не является одновременно &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левым и &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правым.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Виды_ребер.png|600px|thumb|center|П-левые и П-правые ребра]]&lt;br /&gt;
&lt;br /&gt;
Будем называть &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-циклом простой цикл, который содержит ровно одно &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левое и одно &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правое ребро, при этом &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левое ребро входит в вершину &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;. Любой &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-цикл ограничивает &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; {{---}} кратчайший ограничивающий &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt; цикл. Тогда существует &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-цикл такой же длины.&lt;br /&gt;
|proof=&lt;br /&gt;
&amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt; {{---}} кратчайший путь между &amp;lt;math&amp;gt;\xi^s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi^t&amp;lt;/math&amp;gt;, поэтому любой содержащийся в &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt; путь между &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi_j&amp;lt;/math&amp;gt; также кратчайший. При этом любой ограничиващий &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt; цикл обязан пересекать &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;. Цикл, не являющийся &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-циклом, не будет кратчайшим, так как его можно будет сократить вдоль пути &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Для поиска минимального &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-цикла построим из неориентированного графа &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; ориентированный граф &amp;lt;math&amp;gt;\vec{G}^d&amp;lt;/math&amp;gt; следующим образом: все &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левые ребра ориентируем из вершин &amp;lt;math&amp;gt;\xi\in\Pi&amp;lt;/math&amp;gt;, все &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правые ребра ориентируем в вершины &amp;lt;math&amp;gt;\xi\in\Pi&amp;lt;/math&amp;gt;, а остальные ребра &amp;lt;math&amp;gt;u\leftrightarrow v&amp;lt;/math&amp;gt; заменим на два ребра &amp;lt;math&amp;gt;u\rightarrow v&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;v\rightarrow u&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\xi_i\in\Pi&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;P_i&amp;lt;/math&amp;gt; {{---}} кратчайший нетривиальный путь из &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\vec{G}^d&amp;lt;/math&amp;gt;. Тогда соответствующий путь в &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt; является кратчайшим &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-циклом.&lt;br /&gt;
|proof=&lt;br /&gt;
Из определения &amp;lt;math&amp;gt;\vec{G}^d&amp;lt;/math&amp;gt; следует, что если нетривиальный путь из &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; содержит больше одного &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-правого или &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;-левого ребра, то в нем есть самопересечение, то есть он не является простым, следовательно, не является кратчайшим &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-циклом.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Таким образом, нахождение минимального &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;-цикла эквивалентно нахождению кратчайшего нетривиального пути из &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\vec{G}^d&amp;lt;/math&amp;gt;. Это можно сделать за &amp;lt;math&amp;gt;O(m\log n)&amp;lt;/math&amp;gt;, например, с помощью [[алгоритм Дейкстры | алгоритма Дейкстры]]. Так как в планарных графах &amp;lt;math&amp;gt;m=O(n)&amp;lt;/math&amp;gt;, это равно &amp;lt;math&amp;gt;O(n\log n)&amp;lt;/math&amp;gt;. Максимум &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; таких поисков дадут итоговую асимптотику &amp;lt;math&amp;gt;O(n^2\log n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Двойственный граф планарного графа]]&lt;br /&gt;
* [[Разрез, лемма о потоке через разрез]]&lt;br /&gt;
* [[Укладка графа на плоскости]]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [http://verona.dei.unipd.it/~prin08/primo_meeting/italiano.pdf Improved Algorithms for Min Cuts and Max Flows in Undirected Planar Graphs]&lt;br /&gt;
* [https://pdfs.semanticscholar.org/b838/35db99723f922b7b286d10952b08c68970a7.pdf Maximum flow in planar networks, Itai &amp;amp; Shiloach, 1979]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Укладки графов]]&lt;/div&gt;</summary>
		<author><name>Evarand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Xi_cycles.png&amp;diff=58862</id>
		<title>Файл:Xi cycles.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Xi_cycles.png&amp;diff=58862"/>
				<updated>2017-01-05T20:25:10Z</updated>
		
		<summary type="html">&lt;p&gt;Evarand: Кси-циклы, алгоритм поиска разреза в планарном графе&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Кси-циклы, алгоритм поиска разреза в планарном графе&lt;/div&gt;</summary>
		<author><name>Evarand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%92%D0%B8%D0%B4%D1%8B_%D1%80%D0%B5%D0%B1%D0%B5%D1%80.png&amp;diff=58861</id>
		<title>Файл:Виды ребер.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%92%D0%B8%D0%B4%D1%8B_%D1%80%D0%B5%D0%B1%D0%B5%D1%80.png&amp;diff=58861"/>
				<updated>2017-01-05T20:16:26Z</updated>
		
		<summary type="html">&lt;p&gt;Evarand: П-левые и П-правые ребра, алгоритм поиска разреза в планарном графе&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;П-левые и П-правые ребра, алгоритм поиска разреза в планарном графе&lt;/div&gt;</summary>
		<author><name>Evarand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%B0%D1%8F_%D0%BC%D0%B0%D1%82%D0%B5%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B8_%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D1%8B_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85&amp;diff=58857</id>
		<title>Дискретная математика, алгоритмы и структуры данных</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%B0%D1%8F_%D0%BC%D0%B0%D1%82%D0%B5%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B8_%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D1%8B_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85&amp;diff=58857"/>
				<updated>2017-01-05T20:02:30Z</updated>
		
		<summary type="html">&lt;p&gt;Evarand: /* Укладки графов */ добавлен алгоритм поиска разреза&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория:Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
Убедительная просьба читать [[Обсуждение:Дискретная_математика_и_алгоритмы | правила оформления вики-конспектов]].&lt;br /&gt;
&lt;br /&gt;
Символом &amp;lt;tex&amp;gt; \star &amp;lt;/tex&amp;gt; помечены дополнительные темы (возможно, сложные), которые не были подробно рассмотрены (или вообще рассмотрены) в рамках курса.&lt;br /&gt;
&lt;br /&gt;
= Первый семестр =&lt;br /&gt;
&lt;br /&gt;
== Отношения ==&lt;br /&gt;
*[[Определение отношения]]&lt;br /&gt;
*[[Композиция отношений|Композиция отношений, степень отношения, обратное отношение]]&lt;br /&gt;
*[[Рефлексивное отношение|Рефлексивное отношение. Антирефлексивное отношение.]]&lt;br /&gt;
*[[Симметричное отношение]]&lt;br /&gt;
*[[Антисимметричное отношение]]&lt;br /&gt;
*[[Транзитивное отношение]]&lt;br /&gt;
*[[Отношение порядка]]&lt;br /&gt;
*[[Изоморфизмы упорядоченных множеств]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
*[[Отношение эквивалентности]]&lt;br /&gt;
*[[Транзитивное замыкание|Транзитивное замыкание отношения]]&lt;br /&gt;
*[[Алгоритм Флойда — Уоршелла|Алгоритм Флойда-Уоршалла построения транзитивного замыкания отношения]]&lt;br /&gt;
*[[Транзитивный остов]]&lt;br /&gt;
&lt;br /&gt;
== Булевы функции ==&lt;br /&gt;
*[[Определение булевой функции]]&lt;br /&gt;
*[[Побитовые операции]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
*[[Суперпозиции]]&lt;br /&gt;
*[[ДНФ]]&lt;br /&gt;
*[[Сокращенная и минимальная ДНФ | Сокращенная и минимальная ДНФ, минимизация ДНФ методами гиперкубов, карт Карно, Квайна]]&lt;br /&gt;
*[[КНФ]]&lt;br /&gt;
*[[2-SAT]]&lt;br /&gt;
*[[XOR-SAT]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
*[[Специальные формы КНФ|Специальные формы КНФ: КНФ в форме Хорна и КНФ в форме Крома]]&lt;br /&gt;
*[[Полином Жегалкина | Полином Жегалкина, преобразование Мёбиуса]]&lt;br /&gt;
*[[Полные системы функций. Теорема Поста о полной системе функций]]&lt;br /&gt;
*[[Представление функции класса DM с помощью медианы]]&lt;br /&gt;
*[[Пороговая функция]]&lt;br /&gt;
*[[Троичная логика]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схемы из функциональных элементов ==&lt;br /&gt;
*[[Реализация булевой функции схемой из функциональных элементов]]&lt;br /&gt;
*[[Простейшие методы синтеза схем из функциональных элементов]]&lt;br /&gt;
*[[Метод Лупанова синтеза схем]]&lt;br /&gt;
*[[Cумматор]]&lt;br /&gt;
*[[Каскадный сумматор]]&lt;br /&gt;
*[[Двоичный каскадный сумматор]]&lt;br /&gt;
*[[Троичный сумматор]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
*[[Реализация вычитания сумматором]]&lt;br /&gt;
*[[Матричный умножитель]]&lt;br /&gt;
*[[Дерево Уоллеса]]&lt;br /&gt;
*[[Контактная схема]]&lt;br /&gt;
*[[Триггеры]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
*[[Квантовые гейты]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Представление информации ==&lt;br /&gt;
*[[Кодирование информации]]&lt;br /&gt;
*[[Представление целых чисел: прямой код, код со сдвигом, дополнительный код]]&lt;br /&gt;
*[[Представление вещественных чисел]]&lt;br /&gt;
*[[Представление символов, таблицы кодировок]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Алгоритмы сжатия ==&lt;br /&gt;
* [[Алгоритм Хаффмана]]&lt;br /&gt;
* [[Оптимальное хранение словаря в алгоритме Хаффмана]]&lt;br /&gt;
* [[Алгоритм Хаффмана за O(n)]]&lt;br /&gt;
* [[Алгоритм Ху-Таккера]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Неравенство Крафта]]&lt;br /&gt;
* [[Неравенство Макмиллана]]&lt;br /&gt;
* [[Код Шеннона]]&lt;br /&gt;
* [[Оптимальный префиксный код с длиной кодового слова не более L бит]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Алгоритмы LZ77 и LZ78]]&lt;br /&gt;
* [[Алгоритм LZW]]&lt;br /&gt;
* [[Алгоритм LZSS]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Алгоритм LZMA]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Преобразование Барроуза-Уиллера | Преобразование Барроуза-Уиллера и обратное ему]]&lt;br /&gt;
* [[Преобразование MTF]]&lt;br /&gt;
* [[Расстояние Хэмминга]]&lt;br /&gt;
* [[Избыточное кодирование, код Хэмминга]]&lt;br /&gt;
* [[Гамма-, дельта- и омега-код Элиаса]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Комбинаторика ==&lt;br /&gt;
=== Комбинаторные объекты ===&lt;br /&gt;
* [[Комбинаторные объекты]]&lt;br /&gt;
* [[Лексикографический порядок]]&lt;br /&gt;
* [[Коды Грея]]&lt;br /&gt;
* [[Коды Грея для перестановок]]&lt;br /&gt;
* [[Коды антигрея]]&lt;br /&gt;
* [[Монотонный код Грея]]&lt;br /&gt;
* [[Цепные коды]]&lt;br /&gt;
* [[Правильные скобочные последовательности]]&lt;br /&gt;
&lt;br /&gt;
=== Генерация комбинаторных объектов ===&lt;br /&gt;
* [[Генерация комбинаторных объектов в лексикографическом порядке]]&lt;br /&gt;
* [[Получение номера по объекту]]&lt;br /&gt;
* [[Получение объекта по номеру]]&lt;br /&gt;
* [[Получение следующего объекта]]&lt;br /&gt;
* [[Получение предыдущего объекта]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;  &lt;br /&gt;
* [[Метод генерации случайной перестановки, алгоритм Фишера-Йетса]]&lt;br /&gt;
* [[Методы генерации случайного сочетания]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Подсчёт числа объектов ===&lt;br /&gt;
* [[Формула включения-исключения | Формула включения-исключения, подсчет числа беспорядков]]&lt;br /&gt;
* [[Нахождение количества разбиений числа на слагаемые | Нахождение количества разбиений числа на слагаемые. Пентагональная теорема Эйлера]]&lt;br /&gt;
* [[Производящая функция]]&lt;br /&gt;
* [[Лемма Бёрнсайда и Теорема Пойа]]&lt;br /&gt;
* [[Задача об ожерельях]]&lt;br /&gt;
* [[Числа Стирлинга первого рода]]&lt;br /&gt;
* [[Числа Стирлинга второго рода]]&lt;br /&gt;
* [[Числа Эйлера I и II рода | Числа Эйлера первого и второго рода. Подъемы в перестановках]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Числа Каталана]]&lt;br /&gt;
&lt;br /&gt;
=== Свойства комбинаторных объектов ===&lt;br /&gt;
* [[Умножение перестановок, обратная перестановка, группа перестановок]]&lt;br /&gt;
* [[Действие перестановки на набор из элементов, представление в виде циклов]]&lt;br /&gt;
* [[Таблица инверсий]]&lt;br /&gt;
* [[Теорема Кэли]]&lt;br /&gt;
* [[Матричное представление перестановок]]&lt;br /&gt;
* [[Задача о минимуме/максимуме скалярного произведения]]&lt;br /&gt;
* [[Задача о монотонных подпоследовательностях, теорема о связи длины НВП и НУП]]&lt;br /&gt;
&lt;br /&gt;
== [[Динамическое программирование]] ==&lt;br /&gt;
=== Классические задачи динамического программирования ===&lt;br /&gt;
*[[Кратчайший путь в ациклическом графе]]&lt;br /&gt;
*[[Задача о числе путей в ациклическом графе]]&lt;br /&gt;
*[[Задача о расстановке знаков в выражении]]&lt;br /&gt;
*[[Задача о порядке перемножения матриц]]&lt;br /&gt;
*[[Задача о наибольшей общей подпоследовательности]]&lt;br /&gt;
*[[Задача о наибольшей возрастающей подпоследовательности]]&lt;br /&gt;
*[[Задача коммивояжера, ДП по подмножествам]]&lt;br /&gt;
*[[Задача о редакционном расстоянии, алгоритм Вагнера-Фишера]]&lt;br /&gt;
*[[Задача о рюкзаке]]&lt;br /&gt;
&lt;br /&gt;
=== Способы оптимизации методов динамического программирования ===&lt;br /&gt;
*[[Метод четырех русских для умножения матриц]]&lt;br /&gt;
*[[Применение метода четырех русских в задачах ДП на примере задачи о НОП]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
*[[Задача об оптимальном префиксном коде с сохранением порядка. Монотонность точки разреза]]&lt;br /&gt;
*[[Meet-in-the-middle]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Другие задачи ===&lt;br /&gt;
*[[Задача о расстоянии Дамерау-Левенштейна]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
*[[Задача о выводе в контекстно-свободной грамматике, алгоритм Кока-Янгера-Касами]]&lt;br /&gt;
*[[Задача о наибольшей подпоследовательности-палиндроме]]&lt;br /&gt;
*[[Наибольшая общая возрастающая подпоследовательность]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
*[[Задача о наибольшей общей палиндромной подпоследовательности]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
*[[Динамическое программирование по профилю]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
*[[Динамика по поддеревьям]]&lt;br /&gt;
&lt;br /&gt;
== Теория вероятностей ==&lt;br /&gt;
*[[Вероятностное пространство, элементарный исход, событие]]&lt;br /&gt;
*[[Независимые события]]&lt;br /&gt;
*[[Условная вероятность]]&lt;br /&gt;
*[[Формула полной вероятности]]&lt;br /&gt;
*[[Формула Байеса]]&lt;br /&gt;
*[[Дискретная случайная величина]]&lt;br /&gt;
*[[Независимые случайные величины]]&lt;br /&gt;
*[[Математическое ожидание случайной величины]]&lt;br /&gt;
*[[Дисперсия случайной величины]]&lt;br /&gt;
*[[Ковариация случайных величин]]&lt;br /&gt;
*[[Корреляция случайных величин]]&lt;br /&gt;
*[[Неравенство Маркова]]&lt;br /&gt;
*[[Энтропия случайного источника]]&lt;br /&gt;
*[[Симуляция одним распределением другого]]&lt;br /&gt;
*[[Арифметическое кодирование]]&lt;br /&gt;
*[[Парадоксы теории вероятностей]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
*[[Схема Бернулли]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Марковские цепи ==&lt;br /&gt;
&lt;br /&gt;
* [[Марковская цепь]]&lt;br /&gt;
* [[Теорема о поглощении]]&lt;br /&gt;
* [[Фундаментальная матрица]]&lt;br /&gt;
* [[Математическое ожидание времени поглощения]]&lt;br /&gt;
* [[Расчет вероятности поглощения в состоянии]]&lt;br /&gt;
* [[Эргодическая марковская цепь]]&lt;br /&gt;
* [[Регулярная марковская цепь]]&lt;br /&gt;
* [[Примеры использования Марковских цепей]]&lt;br /&gt;
* [[Скрытые Марковские модели]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Алгоритм Витерби]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Алгоритм &amp;quot;Вперед-Назад&amp;quot;]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Алгоритм Баума-Велша]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Второй семестр =&lt;br /&gt;
&lt;br /&gt;
== Амортизационный анализ ==&lt;br /&gt;
* [[Амортизационный анализ]]&lt;br /&gt;
* [[Динамический массив]]&lt;br /&gt;
* [[Hashed Array Tree]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Список]]&lt;br /&gt;
* [[Стек]]&lt;br /&gt;
* [[Очередь]]&lt;br /&gt;
* [[Дек]]&lt;br /&gt;
* [[Мажорирующий элемент]]&lt;br /&gt;
* [[Счетчик Кнута]]&lt;br /&gt;
* [[Мастер-теорема]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[List order maintenance]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Персистентные структуры данных ==&lt;br /&gt;
* [[Персистентные структуры данных]]&lt;br /&gt;
* [[Персистентный стек]]&lt;br /&gt;
* [[Персистентная очередь]]&lt;br /&gt;
* [[Персистентный дек]]&lt;br /&gt;
* [[Персистентная приоритетная очередь]]&lt;br /&gt;
&lt;br /&gt;
== [[Приоритетные очереди]] ==&lt;br /&gt;
* [[Двоичная куча]]&lt;br /&gt;
* [[Биномиальная куча]]&lt;br /&gt;
* [[Фибоначчиева куча]]&lt;br /&gt;
* [[Левосторонняя куча]]&lt;br /&gt;
* [[Тонкая куча]]&lt;br /&gt;
* [[Толстая куча на избыточном счетчике]]&lt;br /&gt;
* [[Куча Бродала-Окасаки]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Система непересекающихся множеств ==&lt;br /&gt;
* [[СНМ (наивные реализации) | Наивные реализации]]&lt;br /&gt;
* [[СНМ (списки с весовой эвристикой) | Списки с весовой эвристикой]]&lt;br /&gt;
* [[СНМ(реализация с помощью леса корневых деревьев) | Реализация с помощью леса корневых деревьев]]&lt;br /&gt;
* [[СНМ с операцией удаления за О(1)]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== [[Поисковые структуры данных]] ==&lt;br /&gt;
* [[Упорядоченное множество]]&lt;br /&gt;
* [[Дерево поиска, наивная реализация]]&lt;br /&gt;
* [[АВЛ-дерево]]&lt;br /&gt;
* [[2-3 дерево]]&lt;br /&gt;
* [[B-дерево]]&lt;br /&gt;
* [[Красно-черное дерево]]&lt;br /&gt;
* [[Декартово дерево]]&lt;br /&gt;
* [[Декартово дерево по неявному ключу]]&lt;br /&gt;
* [[Splay-дерево]]&lt;br /&gt;
* [[Взвешенное дерево]]&lt;br /&gt;
* [[Tango-дерево]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Рандомизированное бинарное дерево поиска]]&lt;br /&gt;
* [[Дерево ван Эмде Боаса]]&lt;br /&gt;
* [[Список с пропусками]]&lt;br /&gt;
* [[Fusion tree]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Сверхбыстрый цифровой бор]]&lt;br /&gt;
* [[Rope]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[AA-дерево]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Дерево отрезков ==&lt;br /&gt;
&lt;br /&gt;
* [[Статистики на отрезках. Корневая эвристика]]&lt;br /&gt;
* [[Дерево отрезков. Построение]]&lt;br /&gt;
* [[Реализация запроса в дереве отрезков сверху]]&lt;br /&gt;
* [[Реализация запроса в дереве отрезков снизу]]&lt;br /&gt;
* [[Несогласованные поддеревья. Реализация массового обновления]]&lt;br /&gt;
* [[Многомерное дерево отрезков]]&lt;br /&gt;
* [[Сжатое многомерное дерево отрезков]]&lt;br /&gt;
&lt;br /&gt;
== Дерево Фенвика ==&lt;br /&gt;
* [[Дерево Фенвика]]&lt;br /&gt;
* [[Встречное дерево Фенвика]]&lt;br /&gt;
* [[Дерево Фенвика для некоммутативных операций]]&lt;br /&gt;
* [[Многомерное дерево Фенвика]]&lt;br /&gt;
&lt;br /&gt;
== Хеширование ==&lt;br /&gt;
* [[Хеш-таблица]]&lt;br /&gt;
* [[Разрешение коллизий]]&lt;br /&gt;
* [[Хеширование кукушки]]&lt;br /&gt;
* [[Идеальное хеширование]]&lt;br /&gt;
* [[Перехеширование]]&lt;br /&gt;
* [[Фильтр Блума]]&lt;br /&gt;
* [[Quotient filter]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Универсальное семейство хеш-функций]]&lt;br /&gt;
* [[Расширяемое хеширование]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== [[Сортировки]] ==&lt;br /&gt;
=== Квадратичные сортировки ===&lt;br /&gt;
* [[Сортировка выбором]]&lt;br /&gt;
* [[Сортировка пузырьком]]&lt;br /&gt;
* [[Сортировка вставками]]&lt;br /&gt;
=== Сортировки на сравнениях ===&lt;br /&gt;
* [[Сортировка Шелла]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Сортировка кучей]]&lt;br /&gt;
* [[Быстрая сортировка]]&lt;br /&gt;
* [[Сортировка слиянием]]&lt;br /&gt;
* [[Cортировка слиянием с использованием O(1) дополнительной памяти]]&lt;br /&gt;
* [[Терпеливая сортировка]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Timsort]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Smoothsort]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Теорема о нижней оценке для сортировки сравнениями]]&lt;br /&gt;
&lt;br /&gt;
=== Многопоточные сортировки ===&lt;br /&gt;
* [[Многопоточная сортировка слиянием]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[PSRS-сортировка]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
=== Другие сортировки ===&lt;br /&gt;
* [[Поиск k-ой порядковой статистики]]&lt;br /&gt;
* [[Поиск k-ой порядковой статистики за линейное время]]&lt;br /&gt;
* [[Поиск k-ой порядковой статистики в двух массивах]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Сортировка подсчетом]]&lt;br /&gt;
* [[Цифровая сортировка]]&lt;br /&gt;
* [[Карманная сортировка]]&lt;br /&gt;
* [[Сортировка Хана]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Задача флага Нидерландов]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Блинная сортировка]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Сортирующие сети ==&lt;br /&gt;
* [[Сортирующие сети]]&lt;br /&gt;
* [[0-1 принцип | Проверка сети компараторов на то, что она сортирующая. 0-1 принцип]]&lt;br /&gt;
* [[Сортирующие сети для квадратичных сортировок]]&lt;br /&gt;
* [[Сортировочные сети с особыми свойствами]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Сеть Бетчера]]&lt;br /&gt;
&lt;br /&gt;
== Алгоритмы поиска ==&lt;br /&gt;
* [[Целочисленный двоичный поиск]]&lt;br /&gt;
* [[Поиск в матрице]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Вещественный двоичный поиск]]&lt;br /&gt;
* [[Троичный поиск]]&lt;br /&gt;
* [[Поиск с помощью золотого сечения]]&lt;br /&gt;
* [[Интерполяционный поиск]]&lt;br /&gt;
* [[Метод Фибоначчи]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Связь между структурами данных ==&lt;br /&gt;
* [[Связь между структурами данных]]&lt;br /&gt;
&lt;br /&gt;
= Третий семестр =&lt;br /&gt;
&lt;br /&gt;
== Основные определения теории графов ==&lt;br /&gt;
* [[Основные определения теории графов|Основные определения: граф, ребро, вершина, степень, петля, путь, цикл]]&lt;br /&gt;
* [[Лемма о рукопожатиях]]&lt;br /&gt;
* [[Теорема о существовании простого пути в случае существования пути]]&lt;br /&gt;
* [[Теорема о существовании простого цикла в случае существования цикла]]&lt;br /&gt;
* [[Матрица смежности графа]]&lt;br /&gt;
* [[Матрица инцидентности графа]]&lt;br /&gt;
* [[Циклическое пространство графа]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Фундаментальные циклы графа]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Дерево, эквивалентные определения]]&lt;br /&gt;
* [[Алгоритмы на деревьях]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Двудольные графы]]&lt;br /&gt;
* [[Дополнительный, самодополнительный граф]]&lt;br /&gt;
* [[Теоретико-множественные операции над графами]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Рёберное ядро]]&lt;br /&gt;
* [[Факторизация графов]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Группы графов]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Гиперграфы]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Связность в графах ==&lt;br /&gt;
* [[Отношение связности, компоненты связности]]&lt;br /&gt;
* [[Отношение реберной двусвязности]]&lt;br /&gt;
* [[Отношение вершинной двусвязности]]&lt;br /&gt;
* [[Точка сочленения, эквивалентные определения]]&lt;br /&gt;
* [[Мост, эквивалентные определения]]&lt;br /&gt;
* [[Граф компонент реберной двусвязности]]&lt;br /&gt;
* [[Граф блоков-точек сочленения]]&lt;br /&gt;
* [[k-связность]]&lt;br /&gt;
* [[Теорема Менгера]]&lt;br /&gt;
* [[Теорема Менгера, альтернативное доказательство]]&lt;br /&gt;
* [[Вершинная, реберная связность, связь между ними и минимальной степенью вершины]]&lt;br /&gt;
&lt;br /&gt;
== Остовные деревья ==&lt;br /&gt;
=== Построение остовных деревьев ===&lt;br /&gt;
* [[Остовные деревья: определения, лемма о безопасном ребре]]&lt;br /&gt;
* [[Алгоритм Прима]]&lt;br /&gt;
* [[Алгоритм Краскала]]&lt;br /&gt;
* [[Алгоритм Борувки]]&lt;br /&gt;
* [[Критерий Тарьяна минимальности остовного дерева|Теорема Тарьяна (критерий минимальности остовного дерева)]]&lt;br /&gt;
* [[Алгоритм двух китайцев]]&lt;br /&gt;
&lt;br /&gt;
=== Свойства остовных деревьев ===&lt;br /&gt;
* [[Матрица Кирхгофа]]&lt;br /&gt;
* [[Связь матрицы Кирхгофа и матрицы инцидентности]]&lt;br /&gt;
* [[Подсчет числа остовных деревьев с помощью матрицы Кирхгофа]]&lt;br /&gt;
* [[Количество помеченных деревьев]]&lt;br /&gt;
* [[Коды Прюфера]]&lt;br /&gt;
&lt;br /&gt;
== Обходы графов ==&lt;br /&gt;
=== Эйлеровы графы ===&lt;br /&gt;
* [[Эйлеров цикл, Эйлеров путь, Эйлеровы графы, Эйлеровость орграфов]]&lt;br /&gt;
* [[Покрытие ребер графа путями]]&lt;br /&gt;
* [[Алгоритм построения Эйлерова цикла]]&lt;br /&gt;
* [[Произвольно вычерчиваемые из заданной вершины графы]]&lt;br /&gt;
* [[Деревья Эйлерова обхода]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Гамильтоновы графы ===&lt;br /&gt;
* [[Гамильтоновы графы]]&lt;br /&gt;
* [[Теорема Хватала]]&lt;br /&gt;
* [[Теорема Дирака]]&lt;br /&gt;
* [[Теорема Оре]]&lt;br /&gt;
* [[Теорема Поша]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Теорема Гуйя-Ури]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Алгоритм нахождения Гамильтонова цикла в условиях теорем Дирака и Оре]]&lt;br /&gt;
* [[Теорема Гринберга]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Турниры]]&lt;br /&gt;
* [[Теорема Редеи-Камиона]]&lt;br /&gt;
&lt;br /&gt;
== Укладки графов ==&lt;br /&gt;
* [[Укладка графа на плоскости]]&lt;br /&gt;
* [[Формула Эйлера]]&lt;br /&gt;
* [[Непланарность K5 и K3,3|Непланарность &amp;lt;tex&amp;gt;K_5&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;K_{3,3}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[Укладка дерева]]&lt;br /&gt;
* [[Укладка графа с планарными компонентами реберной двусвязности]]&lt;br /&gt;
* [[Укладка графа с планарными компонентами вершинной двусвязности]]&lt;br /&gt;
* [[Теорема Понтрягина-Куратовского]]&lt;br /&gt;
* [[Теорема Вагнера]]&lt;br /&gt;
* [[Род, толщина, крупность, число скрещиваний]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Двойственный граф планарного графа]]&lt;br /&gt;
* [[Теорема Фари]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Гамма-алгоритм]]&lt;br /&gt;
* [[Разрез в планарных графах]]&lt;br /&gt;
&lt;br /&gt;
== Раскраски графов ==&lt;br /&gt;
* [[Раскраска графа]]&lt;br /&gt;
* [[Двудольные графы и раскраска в 2 цвета]]&lt;br /&gt;
* [[Хроматический многочлен]]&lt;br /&gt;
* [[Формула Зыкова]]&lt;br /&gt;
* [[Формула Уитни]]&lt;br /&gt;
* [[Теорема Брукса]]&lt;br /&gt;
* [[Верхние и нижние оценки хроматического числа]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Хроматическое число планарного графа]]&lt;br /&gt;
* [[Многочлен Татта]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Теория Рамсея]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Обход в глубину ==&lt;br /&gt;
* [[Обход в глубину, цвета вершин]]&lt;br /&gt;
* [[Лемма о белых путях]]&lt;br /&gt;
* [[Использование обхода в глубину для проверки связности]]&lt;br /&gt;
* [[Использование обхода в глубину для поиска цикла]]&lt;br /&gt;
* [[Использование обхода в глубину для топологической сортировки]]&lt;br /&gt;
* [[Использование обхода в глубину для поиска компонент сильной связности]]&lt;br /&gt;
* [[Использование обхода в глубину для поиска точек сочленения]]&lt;br /&gt;
* [[Построение компонент вершинной двусвязности]]&lt;br /&gt;
* [[Использование обхода в глубину для поиска мостов]]&lt;br /&gt;
* [[Построение компонент реберной двусвязности]]&lt;br /&gt;
&lt;br /&gt;
== Кратчайшие пути в графах ==&lt;br /&gt;
* [[Обход в ширину]]&lt;br /&gt;
* [[Алгоритм Форда-Беллмана]]&lt;br /&gt;
* [[Алгоритм Дейкстры]]&lt;br /&gt;
* [[Алгоритм Флойда]]&lt;br /&gt;
* [[Алгоритм Джонсона]]&lt;br /&gt;
* [[Алгоритм Левита]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Алгоритм A*]] &amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Алгоритм D*]] &amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Эвристики для поиска кратчайших путей]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Задача о паросочетании ==&lt;br /&gt;
* [[Паросочетания: основные определения, теорема о максимальном паросочетании и дополняющих цепях]]&lt;br /&gt;
* [[Алгоритм Форда-Фалкерсона для поиска максимального паросочетания]]&lt;br /&gt;
* [[Алгоритм Куна для поиска максимального паросочетания]]&lt;br /&gt;
* [[Теорема Холла]]&lt;br /&gt;
* [[Связь максимального паросочетания и минимального вершинного покрытия в двудольных графах]]&lt;br /&gt;
* [[Связь вершинного покрытия и независимого множества]]&lt;br /&gt;
* [[Рёберное ядро]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Матрица Татта и связь с размером максимального паросочетания в двудольном графе]]&lt;br /&gt;
* [[Теорема Татта о существовании полного паросочетания]]&lt;br /&gt;
* [[Алгоритм вырезания соцветий|Паросочетания в недвудольных графах. Алгоритм вырезания соцветий]]&lt;br /&gt;
* [[Декомпозиция Эдмондса-Галлаи]]&lt;br /&gt;
* [[Задача об устойчивом паросочетании]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Совершенное паросочетание в кубическом графе]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Задача о максимальном потоке ==&lt;br /&gt;
* [[Определение сети, потока]]&lt;br /&gt;
* [[Разрез, лемма о потоке через разрез]]&lt;br /&gt;
* [[Дополняющая сеть, дополняющий путь]]&lt;br /&gt;
* [[Сложение и разность потоков]]&lt;br /&gt;
* [[Теорема Форда-Фалкерсона]]&lt;br /&gt;
* [[Алгоритм Форда-Фалкерсона, реализация с помощью поиска в глубину]]&lt;br /&gt;
* [[Алоритм Эдмондса-Карпа]]&lt;br /&gt;
* [[Алгоритм масштабирования потока]]&lt;br /&gt;
* [[Блокирующий поток]]&lt;br /&gt;
* [[Схема алгоритма Диница]]&lt;br /&gt;
* [[Теоремы Карзанова о числе итераций алгоритма Диница в сети с целочисленными пропускными способностями]]&lt;br /&gt;
* [[Алгоритм Голдберга-Тарьяна]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Алгоритм поиска блокирующего потока в ациклической сети]]&lt;br /&gt;
* [[Метод проталкивания предпотока]]&lt;br /&gt;
* [[Алгоритм &amp;quot;поднять-в-начало&amp;quot;]]&lt;br /&gt;
* [[Теорема о декомпозиции]]&lt;br /&gt;
* [[Теорема о декомпозиционном барьере]]&lt;br /&gt;
* [[Циркуляция потока]]&lt;br /&gt;
* [[Алгоритм Каргера для нахождения минимального разреза]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Примеры сведения к задачам поиска потока]]&lt;br /&gt;
&lt;br /&gt;
== Задача о потоке минимальной стоимости ==&lt;br /&gt;
* [[Поток минимальной стоимости]]&lt;br /&gt;
* [[Теорема Форда-Фалкерсона о потоке минимальной стоимости]]&lt;br /&gt;
* [[Лемма об эквивалентности свойства потока быть минимальной стоимости и отсутствии отрицательных циклов в остаточной сети]]&lt;br /&gt;
* [[Поиск потока минимальной стоимости методом дополнения вдоль путей минимальной стоимости]]&lt;br /&gt;
* [[Использование потенциалов Джонсона при поиске потока минимальной стоимости]]&lt;br /&gt;
* [[Сведение задачи о назначениях к задаче о потоке минимальной стоимости]]&lt;br /&gt;
* [[Венгерский алгоритм решения задачи о назначениях]]&lt;br /&gt;
* [[Алгоритм отмены цикла минимального среднего веса]]&lt;br /&gt;
&lt;br /&gt;
= Четвертый семестр =&lt;br /&gt;
&lt;br /&gt;
== Основные определения. Простые комбинаторные свойства слов ==&lt;br /&gt;
* [[Основные определения, связанные со строками]]&lt;br /&gt;
* [[Период и бордер, их связь]]&lt;br /&gt;
* [[Слово Фибоначчи]]&lt;br /&gt;
* [[Слово Туэ-Морса]]&lt;br /&gt;
* [[Декомпозиция Линдона]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Алгоритм Ландау-Шмидта]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Алгоритм Крочемора]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Алгоритм Мейна-Лоренца]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Алгоритм Манакера]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Дерево палиндромов]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== [[Поиск подстроки в строке]] ==&lt;br /&gt;
=== Точный поиск ===&lt;br /&gt;
* [[Наивный алгоритм поиска подстроки в строке]]&lt;br /&gt;
* [[Поиск подстроки в строке с использованием хеширования. Алгоритм Рабина-Карпа]]&lt;br /&gt;
* [[Поиск наибольшей общей подстроки двух строк с использованием хеширования]]&lt;br /&gt;
* [[Префикс-функция]]&lt;br /&gt;
* [[Алгоритм Кнута-Морриса-Пратта]]&lt;br /&gt;
* [[Автомат Кнута-Морриса-Пратта]]&lt;br /&gt;
* [[Z-функция]]&lt;br /&gt;
* [[Бор]]&lt;br /&gt;
* [[Алгоритм Ахо-Корасик]]&lt;br /&gt;
* [[Суффиксный автомат]]&lt;br /&gt;
* [[Алгоритм Бойера-Мура]]&lt;br /&gt;
* [[Алгоритм Апостолико-Крочемора]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Алгоритм Колусси]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Алгоритм Райта]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Алгоритм Shift-And]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Двусторонний алгоритм]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Турбо-алгоритм Бойера-Мура]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Нечёткий поиск ===&lt;br /&gt;
* [[Алгоритм Ландау-Вишкина (k несовпадений)]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Алгоритм Ландау-Вишкина (k различий)]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Суффиксное дерево ==&lt;br /&gt;
* [[Суффиксный бор]]&lt;br /&gt;
* [[Сжатое суффиксное дерево]]&lt;br /&gt;
* [[Алгоритм Укконена]]&lt;br /&gt;
* [[Алгоритм МакКрейта]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Алгоритм Фарача]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Суффиксный массив ==&lt;br /&gt;
* [[Суффиксный массив]]&lt;br /&gt;
* [[Построение суффиксного массива с помощью стандартных методов сортировки]]&lt;br /&gt;
* [[Алгоритм цифровой сортировки суффиксов циклической строки]]&lt;br /&gt;
* [[Алгоритм Касаи и др.]]&lt;br /&gt;
* [[Алгоритм Карккайнена-Сандерса]]&lt;br /&gt;
* [[Алгоритм поиска подстроки в строке с помощью суффиксного массива]]&lt;br /&gt;
* [[Количество подпалиндромов в строке]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Задача о наименьшем общем предке ==&lt;br /&gt;
* [[Сведение задачи LCA к задаче RMQ]]&lt;br /&gt;
* [[Сведение задачи RMQ к задаче LCA]]&lt;br /&gt;
* [[Метод двоичного подъема]]&lt;br /&gt;
* [[Решение RMQ с помощью разреженной таблицы]]&lt;br /&gt;
* [[Алгоритм Фарака-Колтона и Бендера]] (решение +/-1 RMQ с помощью метода четырех русских)&lt;br /&gt;
* [[Алгоритм Хьюи]]&lt;br /&gt;
* [[Heavy-light декомпозиция]]&lt;br /&gt;
* [[Алгоритм Шибера-Вишкина]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Алгоритм Тарьяна поиска LCA за O(1) в оффлайн]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Link-Cut Tree]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
* [[Rake-Compress деревья]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Матроиды ==&lt;br /&gt;
=== Основные факты теории матроидов ===&lt;br /&gt;
* [[Определение матроида]]&lt;br /&gt;
* [[Примеры матроидов]]&lt;br /&gt;
* [[Прямая сумма матроидов]]&lt;br /&gt;
* [[Теорема Радо-Эдмондса (жадный алгоритм)]]&lt;br /&gt;
* [[Теорема о базах]]&lt;br /&gt;
* [[Аксиоматизация матроида базами]]&lt;br /&gt;
* [[Теорема о циклах]]&lt;br /&gt;
* [[Аксиоматизация матроида циклами]]&lt;br /&gt;
* [[Ранговая функция, полумодулярность]]&lt;br /&gt;
* [[Аксиоматизация матроида рангами]]&lt;br /&gt;
* [[Двойственный матроид]]&lt;br /&gt;
* [[Оператор замыкания для матроидов]]&lt;br /&gt;
* [[Покрытия, закрытые множества]]&lt;br /&gt;
* [[Матроид Вамоса]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Пересечение матроидов ===&lt;br /&gt;
* [[Пересечение матроидов, определение, примеры]]&lt;br /&gt;
* [[Граф замен]]&lt;br /&gt;
* [[Алгоритм построения базы в пересечении матроидов]]&lt;br /&gt;
&lt;br /&gt;
=== Объединение матроидов ===&lt;br /&gt;
* [[Объединение матроидов, проверка множества на независимость]]&lt;br /&gt;
* [[Объединение матроидов, доказательство того, что объединение является матроидом]]&lt;br /&gt;
* [[Алгоритм построения базы в объединении матроидов]]&lt;br /&gt;
&lt;br /&gt;
== Теория расписаний ==&lt;br /&gt;
=== Общая теория ===&lt;br /&gt;
* [[Классификация задач]]&lt;br /&gt;
* [[Методы решения задач теории расписаний]]&lt;br /&gt;
* [[Правило Лаулера]]&lt;br /&gt;
&lt;br /&gt;
=== Задачи с одним станком ===&lt;br /&gt;
* [[1sumu|&amp;lt;tex&amp;gt;1 \mid \mid \sum U_{i}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[1sumwu|&amp;lt;tex&amp;gt; 1 \mid\mid \sum w_i U_i &amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[1sumwT|&amp;lt;tex&amp;gt; 1 \mid\mid \sum w_i T_i &amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[1p1sumu|&amp;lt;tex&amp;gt;1 \mid p_{i} = 1 \mid \sum U_{i}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[1ridipi1|&amp;lt;tex&amp;gt;1 \mid r_{i}, d_{i}, p_{i} = 1 \mid -&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[1pi1sumwu|&amp;lt;tex&amp;gt;1 \mid p_{i} = 1 \mid \sum w_{i}U_{i}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[1ripi1sumwc|&amp;lt;tex&amp;gt;1 \mid r_{i}, p_i=1\mid \sum w_{i}C_{i}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[1ripi1sumf|&amp;lt;tex&amp;gt;1 \mid r_i, p_i = 1 \mid \sum f_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[1ripipsumwu|&amp;lt;tex&amp;gt; 1 \mid r_i,p_i=p \mid \sum w_i U_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[1ripippmtnsumwu| &amp;lt;tex&amp;gt; 1 \mid r_i,p_i=p, pmtn \mid \sum w_i U_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[1ripmtnsumwu|&amp;lt;tex&amp;gt;1 \mid r_i, pmtn \mid \sum w_{i}U_{i}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[1outtreesumwc | &amp;lt;tex&amp;gt;1 \mid outtree \mid \sum w_i C_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[1precpmtnrifmax|&amp;lt;tex&amp;gt;1 \mid prec, pmtn, r_i \mid f_{\max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[1precripi1Lmax|&amp;lt;tex&amp;gt;1 \mid prec; r_i; p_i = 1 \mid L_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
=== Специальные случаи задач для двух станков ===&lt;br /&gt;
* [[P2precpi1Lmax|&amp;lt;tex&amp;gt;P2 \mid prec, p_i = 1 \mid L_{\max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[R2Cmax|&amp;lt;tex&amp;gt;R2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[F2Cmax|&amp;lt;tex&amp;gt;F2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[O2Cmax|&amp;lt;tex&amp;gt;O2 \mid \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[J2ni2Cmax|&amp;lt;tex&amp;gt;J2 \mid n_{i} \leqslant 2 \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[J2pij1Lmax| &amp;lt;tex&amp;gt;J2\mid p_{ij} = 1\mid L_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
=== Задачи для произвольного числа станков ===&lt;br /&gt;
* [[Flow shop]]&lt;br /&gt;
* [[Fpij1sumwu|&amp;lt;tex&amp;gt;F \mid p_{ij} = 1 \mid \sum w_i U_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[PSumCi|&amp;lt;tex&amp;gt;P \mid \mid \sum C_{i}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[Pintreepi1Lmax|&amp;lt;tex&amp;gt;P \mid intree, p_{i} = 1 \mid L_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[PpmtnriLmax|&amp;lt;tex&amp;gt;P \mid pmtn, r_i \mid L_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[Ppi1sumwu|&amp;lt;tex&amp;gt;P \mid p_i=1 \mid \sum w_i U_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[Ppi1riintegerLmax|&amp;lt;tex&amp;gt;P \mid p_i=1; r_i - integer \mid L_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[RSumCi|&amp;lt;tex&amp;gt;R \mid \mid \sum C_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[RpmtnCmax|&amp;lt;tex&amp;gt;R \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[QpmtnCmax|&amp;lt;tex&amp;gt;Q \mid pmtn \mid C_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[QpmtnSumCi|&amp;lt;tex&amp;gt; Q \mid pmtn \mid \sum C_i &amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[QpmtnriLmax|&amp;lt;tex&amp;gt;Q \mid pmtn, r_{i} \mid L_{max}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[QSumCi|&amp;lt;tex&amp;gt;Q\mid\mid\sum{C_i}&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[Opi1sumu|&amp;lt;tex&amp;gt;O \mid p_{ij} = 1 \mid \sum U_i&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[Opij1di|&amp;lt;tex&amp;gt;O \mid p_{ij} = 1, d_i \mid - &amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[Opij1sumwu|&amp;lt;tex&amp;gt; O \mid p_{i,j} = 1 \mid \sum w_{i} U_{i} &amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[Opij1SumTi|&amp;lt;tex&amp;gt; O \mid p_{i,j} = 1 \mid \sum T_{i} &amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[Opij1Cmax|&amp;lt;tex&amp;gt; O \mid p_{ij} = 1 \mid C_{max} &amp;lt;/tex&amp;gt;]]&lt;br /&gt;
* [[Opij1Sumwc|&amp;lt;tex&amp;gt; O \mid p_{ij} = 1 \mid \sum w_i C_i &amp;lt;/tex&amp;gt;]]&lt;/div&gt;</summary>
		<author><name>Evarand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B0%D0%B7%D1%80%D0%B5%D0%B7_%D0%B2_%D0%BF%D0%BB%D0%B0%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D1%85_%D0%B3%D1%80%D0%B0%D1%84%D0%B0%D1%85&amp;diff=58623</id>
		<title>Разрез в планарных графах</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B0%D0%B7%D1%80%D0%B5%D0%B7_%D0%B2_%D0%BF%D0%BB%D0%B0%D0%BD%D0%B0%D1%80%D0%BD%D1%8B%D1%85_%D0%B3%D1%80%D0%B0%D1%84%D0%B0%D1%85&amp;diff=58623"/>
				<updated>2017-01-04T00:05:58Z</updated>
		
		<summary type="html">&lt;p&gt;Evarand: Алгоритм за O(n^2 logn)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Особенности [[укладка графа на плоскости | планарных графов]] позволяют реализовать поиск [[разрез, лемма о потоке через разрез | минимального разреза]] в планарном графе с лучшей асимптотикой, чем в произвольном графе. Лучший известный алгоритм работает с асимптотикой &amp;lt;math&amp;gt;O(n\log n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Алгоритм за &amp;lt;math&amp;gt;O(n^2 \log n)&amp;lt;/math&amp;gt;==&lt;br /&gt;
Рассмотрим неориентированный граф &amp;lt;math&amp;gt;G=(V, E)&amp;lt;/math&amp;gt;. Будем считать его трёхсвязным, если это не так, [[теорема Фари | триангулируем]] его, используя ребра нулевой пропускной способности, это не изменит значение минимального &amp;lt;math&amp;gt;(s-t)-&amp;lt;/math&amp;gt; разреза. Минимальный разрез исходного графа будет состоять из ребер минимального разреза нового графа, которые есть и в исходном графе.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; трёхсвязен, поэтому существует единственный [[двойственный граф планарного графа | двойственный]] ему граф &amp;lt;math&amp;gt;G^d=(X, A)&amp;lt;/math&amp;gt;, при этом &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt; также трёхсвязен. Будем обозначать множество граней &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; как &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt;, множество граней &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt; как &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;. Между элементами каждой из пар множеств &amp;lt;math&amp;gt;V-\Phi&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;E-A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;F-X&amp;lt;/math&amp;gt; существует взаимно однозначное соответствие. Будем обозначать как &amp;lt;math&amp;gt;\alpha^d\in E&amp;lt;/math&amp;gt; элемент, соответствующий &amp;lt;math&amp;gt;\alpha\in A&amp;lt;/math&amp;gt;. Тогда длину ребра &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; определим как &amp;lt;math&amp;gt;l(\alpha)=c(\alpha^d)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем обозначать грани &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;, соответствующие вершинам &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt;, как &amp;lt;math&amp;gt;\varphi_s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt; соответственно. Далее будем считать, что &amp;lt;math&amp;gt;\varphi_s&amp;lt;/math&amp;gt; {{---}} внешняя грань &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; {{---}} минимальный &amp;lt;math&amp;gt;(s-t)-&amp;lt;/math&amp;gt; разрез, тогда &amp;lt;math&amp;gt;C^d=\{\alpha | \alpha^d\in C\}&amp;lt;/math&amp;gt; {{---}} цикл минимальной длины, ограничивающий &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Формальное доказательство леммы громоздкое и здесь приведено не будет, однако сама лемма достаточно интуитивно понятна.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\xi^s\in\varphi_s&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\xi^t\in\varphi_t&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\Pi=(\xi^s=\xi_1, \ldots, \xi_k=\xi^t)&amp;lt;/math&amp;gt; {{---}} кратчайший путь между &amp;lt;math&amp;gt;\xi^s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi^t&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\alpha_i&amp;lt;/math&amp;gt; {{---}} ребро между &amp;lt;math&amp;gt;\xi_{i-1}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; для &amp;lt;math&amp;gt;i=2,\ldots,k&amp;lt;/math&amp;gt;. Будем называть ребро &amp;lt;math&amp;gt;\xi-\xi_i\in A&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;\Pi-&amp;lt;/math&amp;gt; левым, если оно находится между &amp;lt;math&amp;gt;\alpha_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\alpha_{i+1}&amp;lt;/math&amp;gt; при обходе ребер, входящих в  &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;, по часовой стрелке от &amp;lt;math&amp;gt;\alpha_i&amp;lt;/math&amp;gt;, и &amp;lt;math&amp;gt;\Pi-&amp;lt;/math&amp;gt; правым, если оно находится между &amp;lt;math&amp;gt;\alpha_{i+1}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\alpha_i&amp;lt;/math&amp;gt;.&lt;br /&gt;
Для того, чтобы это определение имело смысл для первой и последней вершин пути, можно добавить две вершины &amp;lt;math&amp;gt;\xi_0&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi_{k+1}&amp;lt;/math&amp;gt; и два ребра &amp;lt;math&amp;gt;\alpha_1=\xi_0-\xi_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\alpha_{k+1}=\xi_k-\xi_{k+1}&amp;lt;/math&amp;gt;. Важно, что никакое ребро не является одновременно &amp;lt;math&amp;gt;\Pi-&amp;lt;/math&amp;gt; левым и &amp;lt;math&amp;gt;\Pi-&amp;lt;/math&amp;gt; правым.&lt;br /&gt;
&lt;br /&gt;
Будем называть &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; - циклом простой цикл, который содержит ровно одно &amp;lt;math&amp;gt;\Pi-&amp;lt;/math&amp;gt; левое и одно &amp;lt;math&amp;gt;\Pi-&amp;lt;/math&amp;gt; правое ребро, при этом &amp;lt;math&amp;gt;\Pi-&amp;lt;/math&amp;gt; левое ребро входит в вершину &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt;. Любой &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; - цикл ограничивает &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; {{---}} кратчайший ограничивающий &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt; цикл. Тогда существует &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; - цикл такой же длины.&lt;br /&gt;
|proof=&lt;br /&gt;
&amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt; {{---}} кратчайший путь между &amp;lt;math&amp;gt;\xi^s&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi^t&amp;lt;/math&amp;gt;, поэтому любой содержащийся в &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt; путь между &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\xi_j&amp;lt;/math&amp;gt; также кратчайший. При этом любой ограничиващий &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt; цикл обязан пересекать &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;. Цикл, не являющийся &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; - циклом, не будет кратчайшим, так как его можно будет сократить вдоль пути &amp;lt;math&amp;gt;\Pi&amp;lt;/math&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Из леммы следует алгоритм нахождения минимального ограничивающего &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt; цикла:&lt;br /&gt;
# Для &amp;lt;math&amp;gt;i=1,\ldots,k&amp;lt;/math&amp;gt; найдем минимальный &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; - цикл&lt;br /&gt;
# Кратчайший из этих &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; путей будет минимальным ограничивающим &amp;lt;math&amp;gt;\varphi_t&amp;lt;/math&amp;gt; циклом&lt;br /&gt;
&lt;br /&gt;
Для поиска минимального &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; - цикла построим из неориентированного графа &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; ориентированный граф &amp;lt;math&amp;gt;\vec{G}^d&amp;lt;/math&amp;gt; следующим образом: все &amp;lt;math&amp;gt;\Pi-&amp;lt;/math&amp;gt; левые ребра ориентируем из вершин &amp;lt;math&amp;gt;\xi\in\Pi&amp;lt;/math&amp;gt;, все &amp;lt;math&amp;gt;\Pi-&amp;lt;/math&amp;gt; правые ребра ориентируем в вершины &amp;lt;math&amp;gt;\xi\in\Pi&amp;lt;/math&amp;gt;, а остальные ребра &amp;lt;math&amp;gt;u-v&amp;lt;/math&amp;gt; заменим на два ребра &amp;lt;math&amp;gt;u\rightarrow v&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;v\rightarrow u&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;\xi_i\in\Pi&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;P_i&amp;lt;/math&amp;gt; {{---}} кратчайший нетривиальный путь из &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\vec{G}^d&amp;lt;/math&amp;gt;. Тогда соответствующий путь в &amp;lt;math&amp;gt;G^d&amp;lt;/math&amp;gt; является кратчайшим &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; - циклом.&lt;br /&gt;
|proof=&lt;br /&gt;
Из определения &amp;lt;math&amp;gt;\vec{G}^d&amp;lt;/math&amp;gt; следует, что если нетривиальный путь из &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; содержит больше одного &amp;lt;math&amp;gt;\Pi-&amp;lt;/math&amp;gt; правого или &amp;lt;math&amp;gt;\Pi-&amp;lt;/math&amp;gt; левого ребра, то в нем есть самопересечение, то есть он не является простым, следовательно, не является кратчайшим &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; - циклом.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Таким образом, нахождение минимального &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; - цикла эквивалентно нахождению кратчайшего нетривиального пути из &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\xi_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\vec{G}^d&amp;lt;/math&amp;gt;. Это можно сделать за &amp;lt;math&amp;gt;O(m\log n)&amp;lt;/math&amp;gt;, например, с помощью [[алгоритм Дейкстры | алгоритма Дейкстры]]. Так как в планарных графах &amp;lt;math&amp;gt;m=O(n)&amp;lt;/math&amp;gt;, это равно &amp;lt;math&amp;gt;O(n\log n)&amp;lt;/math&amp;gt;. Максимум &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; таких поисков дадут итоговую асимптотику &amp;lt;math&amp;gt;O(n^2\log n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Двойственный граф планарного графа]]&lt;br /&gt;
* [[Разрез, лемма о потоке через разрез]]&lt;br /&gt;
* [[Укладка графа на плоскости]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [http://verona.dei.unipd.it/~prin08/primo_meeting/italiano.pdf: Improved Algorithms for Min Cuts and Max Flows in Undirected Planar Graphs]&lt;br /&gt;
* [https://pdfs.semanticscholar.org/b838/35db99723f922b7b286d10952b08c68970a7.pdf: Maximum flow in planar networks, Itai &amp;amp; Shiloach, 1979]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Укладки графов]]&lt;/div&gt;</summary>
		<author><name>Evarand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0-%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0&amp;diff=50191</id>
		<title>Преобразование Барроуза-Уилера</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0-%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0&amp;diff=50191"/>
				<updated>2015-12-12T19:36:32Z</updated>
		
		<summary type="html">&lt;p&gt;Evarand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
'''Преобразование Барроуза {{---}} Уилера''' (англ. ''Burrows-Wheeler transform'') {{---}} алгоритм, используемый для предварительной обработки данных перед сжатием, разработанный для улучшения эффективности последующего кодирования. Преобразование Барроуза {{---}} Уилера меняет порядок символов во входной строке таким образом, что повторяющиеся подстроки образуют на выходе идущие подряд последовательности одинаковых символов.&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Преобразование выполняется в три этапа:&lt;br /&gt;
# Составляется таблица всех циклических сдвигов входной строки.&lt;br /&gt;
# Производится лексикографическая (в алфавитном порядке) сортировка строк таблицы.&lt;br /&gt;
# В качестве выходной строки выбирается последний столбец таблицы преобразования и номер строки, совпадающей с исходной.&lt;br /&gt;
&lt;br /&gt;
== Пример работы алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дана исходная строка &amp;lt;tex&amp;gt;$s =$&amp;lt;/tex&amp;gt; &amp;quot;ABACABA&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;4&amp;quot;|Трансформация&lt;br /&gt;
|-&lt;br /&gt;
! Вход || Все&amp;lt;br /&amp;gt;циклические &amp;lt;br /&amp;gt; сдвиги || Сортировка&amp;lt;br /&amp;gt;строк || Выход&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
BACABAA&amp;lt;br/&amp;gt;&lt;br /&gt;
ACABAAB&amp;lt;br/&amp;gt;&lt;br /&gt;
CABAABA&amp;lt;br/&amp;gt;&lt;br /&gt;
ABAABAC&amp;lt;br/&amp;gt;&lt;br /&gt;
BAABACA&amp;lt;br/&amp;gt;&lt;br /&gt;
AABACAB&amp;lt;br/&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
AABACAB&amp;lt;br/&amp;gt;&lt;br /&gt;
ABAABAC&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
ACABAAB&amp;lt;br/&amp;gt;&lt;br /&gt;
BAABACA&amp;lt;br/&amp;gt;&lt;br /&gt;
BACABAA&amp;lt;br/&amp;gt;&lt;br /&gt;
CABAABA &amp;lt;br/&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
BCABAAA, 3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Результат можно записать так: &amp;lt;tex&amp;gt;$BWT(s) = $(&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, &amp;lt;tex&amp;gt;3)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; {{---}} номер исходной строки в отсортированной матрице. Он нужен для обратного преобразования. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следует заметить, что иногда в исходной строке приводится так называемый символ конца строки &amp;lt;tex&amp;gt;\$&amp;lt;/tex&amp;gt;, который в преобразовании будет считаться последним (максимальным) символом, тогда сохранение номера исходной строки не требуется.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пусть нам дана исходная строка &amp;lt;tex&amp;gt;$s =$&amp;lt;/tex&amp;gt; &amp;quot;ABACABA$&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;4&amp;quot;|Трансформация&lt;br /&gt;
|-&lt;br /&gt;
! Вход || Все&amp;lt;br /&amp;gt; циклические &amp;lt;br/&amp;gt; сдвиги || Сортировка&amp;lt;br /&amp;gt;строк || Выход&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
BACABA$A&amp;lt;br/&amp;gt;&lt;br /&gt;
ACABA$AB&amp;lt;br/&amp;gt;&lt;br /&gt;
CABA$ABA&amp;lt;br/&amp;gt;&lt;br /&gt;
ABA$ABAC&amp;lt;br/&amp;gt;&lt;br /&gt;
BA$ABACA&amp;lt;br/&amp;gt;&lt;br /&gt;
A$ABACAB&amp;lt;br/&amp;gt;&lt;br /&gt;
$ABACABA&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
ABA$ABAC&amp;lt;br/&amp;gt;&lt;br /&gt;
ACABA$AB&amp;lt;br/&amp;gt;&lt;br /&gt;
A$ABACAB&amp;lt;br/&amp;gt;&lt;br /&gt;
BACABA$A&amp;lt;br/&amp;gt;&lt;br /&gt;
BA$ABACA&amp;lt;br/&amp;gt;&lt;br /&gt;
CABA$ABA &amp;lt;br/&amp;gt;&lt;br /&gt;
$ABACABA&lt;br /&gt;
|&lt;br /&gt;
$CBBAAAA&lt;br /&gt;
|} &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
При аналогичном вышеприведённом преобразовании та строчка в матрице, которая будет заканчиваться на символ конца строки, и будет исходной: (&amp;quot;ABACABA$&amp;quot;). Тогда результат можно записать так: &amp;lt;tex&amp;gt;$BWT(s) =$&amp;lt;/tex&amp;gt; &amp;quot;$CBBAAAA&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Обратное преобразование ==&lt;br /&gt;
&lt;br /&gt;
===Наивный алгоритм===&lt;br /&gt;
&lt;br /&gt;
Пусть нам дано: &amp;lt;tex&amp;gt;$BWT(s) =$(&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, &amp;lt;tex&amp;gt;3)&amp;lt;/tex&amp;gt;. Тогда выпишем в столбик нашу преобразованную последовательность символов &amp;quot;BCABAAA&amp;quot;. Запишем её как последний столбик предыдущей матрицы (при прямом преобразовании Барроуза {{---}} Уилера), при этом все предыдущие столбцы оставляем пустыми. Далее построчно [[Сортировки | отсортируем]] матрицу, затем в предыдущий столбец запишем &amp;quot;BCABAAA&amp;quot;. Опять построчно отсортируем матрицу. Продолжая таким образом, можно восстановить полный список всех циклических сдвигов строки, которую нам надо найти. Выстроив полный отсортированный список сдвигов, выберем строку с номером, который нам был изначально дан. В итоге мы получим искомую строку.&lt;br /&gt;
Алгоритм обратного преобразования описан в таблице ниже:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Обратное преобразование&lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Вход&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot; colspan=&amp;quot;8&amp;quot;|&lt;br /&gt;
BCABAAA&lt;br /&gt;
|-&lt;br /&gt;
! Добавление 1 || Сортировка 1 || Добавление 2 || Сортировка 2 || Добавление 3 || Сортировка 3 || Добавление 4 &lt;br /&gt;
|-align=&amp;quot;right&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
 B&lt;br /&gt;
 C&lt;br /&gt;
 A&lt;br /&gt;
 B&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
|&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 B&lt;br /&gt;
 B&lt;br /&gt;
 C&lt;br /&gt;
|&lt;br /&gt;
 BA&lt;br /&gt;
 CA&lt;br /&gt;
 AA&lt;br /&gt;
 BA&lt;br /&gt;
 AB&lt;br /&gt;
 AB&lt;br /&gt;
 AC&lt;br /&gt;
|&lt;br /&gt;
 AA&lt;br /&gt;
 AB&lt;br /&gt;
 AB&lt;br /&gt;
 AC&lt;br /&gt;
 BA&lt;br /&gt;
 BA&lt;br /&gt;
 CA&lt;br /&gt;
|&lt;br /&gt;
 BAA&lt;br /&gt;
 CAB&lt;br /&gt;
 AAB&lt;br /&gt;
 BAC&lt;br /&gt;
 ABA&lt;br /&gt;
 ABA&lt;br /&gt;
 ACA&lt;br /&gt;
|&lt;br /&gt;
 AAB&lt;br /&gt;
 ABA&lt;br /&gt;
 ABA&lt;br /&gt;
 ACA&lt;br /&gt;
 BAA&lt;br /&gt;
 BAC&lt;br /&gt;
 CAB&lt;br /&gt;
|&lt;br /&gt;
 BAAB&lt;br /&gt;
 CABA&lt;br /&gt;
 AABA&lt;br /&gt;
 BACA&lt;br /&gt;
 ABAA&lt;br /&gt;
 ABAC&lt;br /&gt;
 ACAB&lt;br /&gt;
|-&lt;br /&gt;
! Сортировка 4 || Добавление 5 || Сортировка 5 || Добавление 6 || Сортировка 6 || Добавление 7 || Сортировка 7&lt;br /&gt;
&lt;br /&gt;
|-align=&amp;quot;right&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
 AABA&lt;br /&gt;
 ABAA&lt;br /&gt;
 ABAC&lt;br /&gt;
 ACAB&lt;br /&gt;
 BAAB&lt;br /&gt;
 BACA&lt;br /&gt;
 CABA&lt;br /&gt;
|&lt;br /&gt;
 BAABA&lt;br /&gt;
 CABAA&lt;br /&gt;
 AABAC&lt;br /&gt;
 BACAB&lt;br /&gt;
 ABAAB&lt;br /&gt;
 ABACA&lt;br /&gt;
 ACABA&lt;br /&gt;
|&lt;br /&gt;
 AABAC&lt;br /&gt;
 ABAAB&lt;br /&gt;
 ABACA&lt;br /&gt;
 ACABA&lt;br /&gt;
 BAABA&lt;br /&gt;
 BACAB&lt;br /&gt;
 CABAA&lt;br /&gt;
|&lt;br /&gt;
 BAABAC&lt;br /&gt;
 CABAAB&lt;br /&gt;
 AABACA&lt;br /&gt;
 BACABA&lt;br /&gt;
 ABAABA&lt;br /&gt;
 ABACAB&lt;br /&gt;
 ACABAA&lt;br /&gt;
|&lt;br /&gt;
 AABACA&lt;br /&gt;
 ABAABA&lt;br /&gt;
 ABACAB&lt;br /&gt;
 ACABAA&lt;br /&gt;
 BAABAC&lt;br /&gt;
 BACABA&lt;br /&gt;
 CABAAB&lt;br /&gt;
|&lt;br /&gt;
 BAABACA&lt;br /&gt;
 CABAABA&lt;br /&gt;
 AABACAB&lt;br /&gt;
 BACABAA&lt;br /&gt;
 ABAABAC&lt;br /&gt;
 ABACABA&lt;br /&gt;
 ACABAAB&lt;br /&gt;
|&lt;br /&gt;
 AABACAB&lt;br /&gt;
 ABAABAC&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
 ACABAAB&lt;br /&gt;
 BAABACA&lt;br /&gt;
 BACABAA&lt;br /&gt;
 CABAABA&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Результат&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot; colspan=&amp;quot;8&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Следует также заметить, что если нам было бы дано &amp;lt;tex&amp;gt;$BWT(s) = $&amp;lt;/tex&amp;gt; &amp;quot;$CBBAAAA&amp;quot;, то мы также получили бы нашу исходную строку, только с символом конца строки &amp;lt;tex&amp;gt;\$&amp;lt;/tex&amp;gt; на конце: ABACABA$.&lt;br /&gt;
&lt;br /&gt;
Временная сложность данного алгоритма &amp;lt;tex&amp;gt;O(N^3\log{N}) &amp;lt;/tex&amp;gt;, пространственная &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Доказательство корректности====&lt;br /&gt;
&lt;br /&gt;
Пусть дана строка &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;, к которой было применено преобразование BWT. Докажем, что при использовании наивного алгоритма на каждом шаге получающийся набор строк соответствует суффиксам циклических сдвигов исходной строки, методом математической индукции.&lt;br /&gt;
* '''База'''. Циклически сдвинем все строки исходной таблицы на &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; влево. Тогда в столбце &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; будут находиться символы, добавленные на первом шаге алгоритма, а в столбце &amp;lt;tex&amp;gt;n - 1&amp;lt;/tex&amp;gt; символы, изначально стоявшие в таблице до первого шага алгоритма. Таким образом, полученные на первом шаге алгоритма строки являются суффиксами циклических сдвигов строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* '''Предположение'''. Пусть на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; шаге алгоритма все полученные строки являются суффиксами циклических сдвигов строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* '''Переход'''. Рассмотрим &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ый шаг алгоритма. Все строки отсортированы, поэтому самый левый столбец совпадет с &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; столбцом исходной таблицы. Циклически сдвинем все строки исходной таблицы на &amp;lt;tex&amp;gt;n - k&amp;lt;/tex&amp;gt; символов вправо. Теперь по предположению первые &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; символов справа в каждой строке совпадают у исходной таблицы и у таблицы, полученной в результате работы алгоритма. &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;-ые справа столбцы также совпадают. Добавленный на &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ом шаге столбец также совпадает с &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ым справа столбцом сдвинутой исходной таблицы, так как совпадает с последним столбцом исходной таблицы, которая была сдвинута на &amp;lt;tex&amp;gt;n-k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;3&amp;quot; | &amp;lt;tex&amp;gt;$k+1$&amp;lt;/tex&amp;gt; шаг алгоритма при &amp;lt;tex&amp;gt;$k=3$&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! Исходная &amp;lt;br /&amp;gt; таблица || Сдвинутая &amp;lt;br /&amp;gt; таблица || Результат &amp;lt;br /&amp;gt; работы &amp;lt;br /&amp;gt; алгоритма&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;CA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt;BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt;AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt;AA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt;AC&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt;BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
CA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
AA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
AC&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:right;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Таким образом, поскольку на каждом шаге алгоритма получившиеся строки являлись суффиксами циклических сдвигов &amp;lt;tex&amp;gt; $s$ &amp;lt;/tex&amp;gt;, после последнего шага получившиеся строки будут совпадать с циклическими сдвигами &amp;lt;tex&amp;gt; $s$ &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Оптимизированный наивный алгоритм===&lt;br /&gt;
&lt;br /&gt;
Наивный алгоритм можно оптимизировать. Заметим, что при каждом проявлении неизвестного столбца выполнялись одни и те же действия. К предыдущему приписывался новый столбец и имеющиеся данные сортировались. На каждом шаге к строке, которая находилась на &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;-ом месте, приписывался в начало &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; -ый элемент столбца входных данных. Пусть изначально известно, каким по порядку является приписанный в начало символ (то есть каким по порядку в столбце). Из предыдущего шага известно, какое место занимала строка без этого первого символа (&amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; -ое). Тогда несложно заметить, что при выполнении такой операции строка с номером &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; всегда будет перемещаться на позицию с номером &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |0||а||&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;||р||9&lt;br /&gt;
  |-&lt;br /&gt;
  |1||а||||д||7&lt;br /&gt;
  |-&lt;br /&gt;
  |2||а|| ||a||0&lt;br /&gt;
  |-&lt;br /&gt;
  |3||а|| ||к||8&lt;br /&gt;
  |-&lt;br /&gt;
  |4||а|| ||р||10&lt;br /&gt;
  |-&lt;br /&gt;
  |5||б|| ||a||1&lt;br /&gt;
  |-&lt;br /&gt;
  |6||б|| ||a||2&lt;br /&gt;
  |-&lt;br /&gt;
  |7||д|| ||a||3&lt;br /&gt;
  |-&lt;br /&gt;
  |8||к|| ||a||4&lt;br /&gt;
  |-&lt;br /&gt;
  |9||р|| ||б||5&lt;br /&gt;
  |-&lt;br /&gt;
  |10||р|| ||б||6&lt;br /&gt;
  |}&lt;br /&gt;
&lt;br /&gt;
Здесь слева отсортированный данный столбец, чтобы мы знали, какое место в лексикографическом порядке занимает приписываемый нами символ среди всех элементов данного нам изначально столбца. Справа - изначально данный столбец и соответствующее ему число. Поскольку в нашем алгоритме новый столбец приписывается в начало, то мы из состояния &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; (левый столбец) переходим в состояние &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; (правый). Для того, чтобы восстановить строку, нам необходимо от последней такой цифры по пути из &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; восстановить строку.&lt;br /&gt;
{|&lt;br /&gt;
 |&lt;br /&gt;
 {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
 |6&lt;br /&gt;
 |→&lt;br /&gt;
 |10&lt;br /&gt;
 |→&lt;br /&gt;
 |4 &lt;br /&gt;
 |→&lt;br /&gt;
 |8&lt;br /&gt;
 |→ &lt;br /&gt;
 |3&lt;br /&gt;
 |→&lt;br /&gt;
 |7&lt;br /&gt;
 |→&lt;br /&gt;
 |1&lt;br /&gt;
 |→&lt;br /&gt;
 |5&lt;br /&gt;
 |→&lt;br /&gt;
 |9&lt;br /&gt;
 |→&lt;br /&gt;
 |0&lt;br /&gt;
 |→&lt;br /&gt;
 |2&lt;br /&gt;
 |-&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |б&lt;br /&gt;
 |&lt;br /&gt;
 |р&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |к&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |д&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |б&lt;br /&gt;
 |&lt;br /&gt;
 |р&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
|}&lt;br /&gt;
====Сложность оптимизированного алгоритма====&lt;br /&gt;
Данный алгоритм работает за &amp;lt;tex&amp;gt;O(N\log{N})&amp;lt;/tex&amp;gt; времени и требует &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt; памяти. Однако, если размер алфавита не очень большой, то для выяснения первого столбца матрицы можно использовать сортировку подсчетом, в этом случае алгоритм работает за &amp;lt;tex&amp;gt;O(N+M)&amp;lt;/tex&amp;gt; действий и требует &amp;lt;tex&amp;gt;O(N+M)&amp;lt;/tex&amp;gt; памяти, где &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; — размер алфавита.&lt;br /&gt;
&lt;br /&gt;
====Псевдокод оптимизированного алгоритма====&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; N &amp;lt;/tex&amp;gt; — количество символов во входной строке, &amp;lt;tex&amp;gt; M &amp;lt;/tex&amp;gt; — количество символов в алфавите, &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; — номер исходной строки в матрице сдвигов, &amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt; — входящая строка, &amp;lt;tex&amp;gt; count &amp;lt;/tex&amp;gt;  — массив для сортировки подсчетом, &amp;lt;tex&amp;gt; t &amp;lt;/tex&amp;gt; — вектор обратного преобразования, &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; — номер данной нам строки в таблице.&lt;br /&gt;
&lt;br /&gt;
  '''function''' reverseBWT(N : Int, M : Int, k : Int, s : String): Int[]&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Cчитаем частоты символов&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' i = 0 .. M &lt;br /&gt;
      count[i] = 0&lt;br /&gt;
    '''for''' i = 0 .. N &lt;br /&gt;
      count[s[i]]++&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Упорядочиваем символы, чтобы получить первый столбец исходной матрицы&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// count[i] указывает на первую позицию символа i в первом столбце&amp;lt;/font&amp;gt;&lt;br /&gt;
    sum = 0&lt;br /&gt;
    '''for''' i = 0 .. M&lt;br /&gt;
      sum = sum + count[i]&lt;br /&gt;
      count[i] = sum - count[i]&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Cоздаем вектор обратного преобразования&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' i = 0 .. N&lt;br /&gt;
    t[count[s[i]]] = i&lt;br /&gt;
    count[s[i]]++&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// И восстанавливаем исходный текст&amp;lt;/font&amp;gt;&lt;br /&gt;
    j = t[x]&lt;br /&gt;
    '''for''' i = 0 .. N&lt;br /&gt;
      answer[i] = s[j]&lt;br /&gt;
      j = t[j]&lt;br /&gt;
    '''return''' answer&lt;br /&gt;
&lt;br /&gt;
====Доказательство корректности====&lt;br /&gt;
&lt;br /&gt;
Пусть текст &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; состоит из &amp;lt;tex&amp;gt;N + 1&amp;lt;/tex&amp;gt; символов, занумерованных с нуля: &amp;lt;tex&amp;gt;T[0..N]&amp;lt;/tex&amp;gt;. Буквы &amp;lt;tex&amp;gt;T[i]&amp;lt;/tex&amp;gt; принадлежат некоторому алфавиту &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Лексикографический порядок (строгий) на строках из алфавита &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; будем обозначать &amp;lt;tex&amp;gt;\preceq (\prec)&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt;S_{k}T&amp;lt;/tex&amp;gt; циклический сдвиг текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; символов влево:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt; S_{k}T = T[(j + k) (\bmod\ N + 1)] &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Существует перестановка &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;\{0, ..., N\}&amp;lt;/tex&amp;gt;, которая удовлетворяет условию: &lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt; S_{p(i)}T \preceq S_{p(i + 1)}T,\ i = 0, ..., N - 1\ \ \textbf{(1)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Преобразование Барроуза-Уилера текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; есть текст &amp;lt;tex&amp;gt;B[0..N] = BW(T)&amp;lt;/tex&amp;gt;, буквы которого заданы соотношением:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt;B[i] = S_{p(i)}T[N]&amp;lt;/tex&amp;gt;, другими словами &amp;lt;tex&amp;gt;B[i] = S_{p(i) - 1}T[0] = T[(p(i) - 1) (\bmod\ N + 1)] \ \ \textbf{(2)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} перестановка чисел &amp;lt;tex&amp;gt;\{0, ..., N\}&amp;lt;/tex&amp;gt;, удовлетворяющая условию:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt;B_{\sigma(i)} \preceq B_{\sigma(i + 1)}&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N - 1\ \ \textbf{(3)}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
|}&lt;br /&gt;
и в случае равенства &amp;lt;tex&amp;gt;B_{\sigma(i)}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;B_{\sigma(i + 1)}&amp;lt;/tex&amp;gt; выполнено {{---}} &amp;lt;tex&amp;gt;\sigma(i) &amp;lt; \sigma(i + 1)&amp;lt;/tex&amp;gt;. Перестановка однозначно определяется текстом &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; и ее можно посчитать за &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt;, используя сортировку подсчетом. Рассмотрим перестановку &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; как отображение &amp;lt;tex&amp;gt;\sigma : \{0, ..., N\} \to \{0, ..., N\}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;\sigma^{k}&amp;lt;/tex&amp;gt; копмозиция &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; отображений &amp;lt;tex&amp;gt;\sigma^{k} = \sigma^{k - 1} \circ \sigma&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\sigma^{1} = \sigma, \sigma^{0} \equiv i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
&lt;br /&gt;
''При всех &amp;lt;tex&amp;gt;m = 1, ..., N + 1&amp;lt;/tex&amp;gt; верны утверждения,&lt;br /&gt;
:&amp;lt;tex&amp;gt;B_{\sigma(i)}...B_{\sigma^{m}(i)} \preceq B_{\sigma(i + 1)}...B_{\sigma^{m}(i + 1)}&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N - 1\ \ \textbf{(4)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;B_iB_{\sigma(i)}...B_{\sigma^{m - 1}(i)} = S_{p(i) - 1}T[0..m - 1]&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N\ \ \textbf{(5)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
|proof=&lt;br /&gt;
&lt;br /&gt;
Если лексикографически отсортировать буквы последнего столбца и поместить их в первый столбец, то получится таблица&lt;br /&gt;
&lt;br /&gt;
| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Таблица&lt;br /&gt;
|-&lt;br /&gt;
|a||b||c&lt;br /&gt;
|-&lt;br /&gt;
|a||b||c&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
&lt;br /&gt;
''Для восстановления исходного текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из преобразования &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; достаточно знать число &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;, отвечающее условию &amp;lt;tex&amp;gt;p(I) = 0&amp;lt;/tex&amp;gt;, другими словами &amp;lt;tex&amp;gt;S_{p(I)}T = T&amp;lt;/tex&amp;gt;.''&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Алгоритм за линейное время===&lt;br /&gt;
&lt;br /&gt;
Будем обозначать &amp;lt;tex&amp;gt;s^i&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ую циклический сдвиг &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;s^0 = s_0 s_1 \ldots s_{n-1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;$BWT(s)$\;= L&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;L = L_0L_1\ldots L_{n-1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; -- номер строки &amp;lt;tex&amp;gt;s^0&amp;lt;/tex&amp;gt; в таблице. Предподсчитаем следующие величины:&lt;br /&gt;
* Для каждого &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt; количество символов на подстроке &amp;lt;tex&amp;gt;l_0, \ldots , l_{i-1}&amp;lt;/tex&amp;gt;, равных &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
* Для каждого уникального &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt; количество символов в &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;, лексикографически меньших, чем &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пример для &amp;lt;tex&amp;gt;$BWT(s) =$&amp;lt;/tex&amp;gt; &amp;quot;BCABAAA&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
!colspan=&amp;quot;3&amp;quot; | Таблица первого предподсчёта&lt;br /&gt;
|-&lt;br /&gt;
! Позиция || Символ || Результат&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
! 0 || B || 0&lt;br /&gt;
|-&lt;br /&gt;
! 1 || C || 0&lt;br /&gt;
|-&lt;br /&gt;
! 2 || A || 0&lt;br /&gt;
|-&lt;br /&gt;
! 3 || B || 1&lt;br /&gt;
|-&lt;br /&gt;
! 4 || A || 1&lt;br /&gt;
|-&lt;br /&gt;
! 5 || A || 2&lt;br /&gt;
|-&lt;br /&gt;
! 6 || A || 3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; | Таблица второго предподсчёта&lt;br /&gt;
|-&lt;br /&gt;
! Символ || Количество  &amp;lt;br /&amp;gt; меньших&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
! A || 0&lt;br /&gt;
|-&lt;br /&gt;
! B || 4&lt;br /&gt;
|-&lt;br /&gt;
! C || 6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Для удобства пронумеруем известные нам данные:&lt;br /&gt;
# &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;, последний столбец таблицы сдвигов&lt;br /&gt;
# &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;, номер строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt; в таблице сдвигов&lt;br /&gt;
# Частота, с которой символ &amp;lt;tex&amp;gt;L_{i}&amp;lt;/tex&amp;gt; встречается в подстроке &amp;lt;tex&amp;gt;l_0, \ldots , l_{i-1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
# Для каждого уникального символа количество лексикографически меньших символов в &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Символ &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt; находится в строке &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; под номером &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;, так как в таблице строка &amp;lt;tex&amp;gt;s^0&amp;lt;/tex&amp;gt; имела номер &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;. Найдём символ &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Символ &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt; имеет в строке &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; тот же номер, что строка &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt; имела в таблице сдвигов: строка &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt; начинается с символа &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt; находится на 1 левее его и из-за циклического сдвига оказывается в последнем столбце. Нам известен символ &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;. Посчитаем, на каком месте в таблице будет стоять строка, начинающаяся с этого символа.&lt;br /&gt;
&lt;br /&gt;
Из 4 известно количество символов, меньших &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;. Все строки, начинающиеся с этих символов, стоят в таблице раньше &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt;. Кроме того, в таблице есть строки, начинающиеся с того же символа, что и &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt;. Из 3 известно, сколько их: если символ, равный &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, встречался в &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; раньше, чем &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, то в таблице строка, начинающаяся с этого символа, тоже стоит раньше строки, начинающейся с &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, так как префикс строки, оканчивающейся на этот символ, меньше префикса строки, оканчивающейся на &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Тогда сумма этих двух величин является номером символа &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt; в строке &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;. Зная &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt;, аналогично найдём &amp;lt;tex&amp;gt;s_{n-3}\ldots s_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предподсчёт занимает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени, восстановление каждого из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; символов занимает &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; времени. Суммарное время работы алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пример работы для &amp;lt;tex&amp;gt;$BWT(s) = ($&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, 2&amp;lt;tex&amp;gt;)&amp;lt;/tex&amp;gt; (нумерация с 0):&lt;br /&gt;
* &amp;lt;tex&amp;gt;s^0 = .......&amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;s_6=L_2 = A&amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt;s^0=......&amp;lt;/tex&amp;gt;A&lt;br /&gt;
* Суммируем значения из двух таблиц: &amp;lt;tex&amp;gt;0+0=0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_5=L_0=B&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=.....&amp;lt;/tex&amp;gt;BA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;0+4=4&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_4=L_4=A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=....&amp;lt;/tex&amp;gt;ABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;1+0=1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_3=L_1=C&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=...&amp;lt;/tex&amp;gt;CABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;0+6=6&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_2=L_6=A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=..&amp;lt;/tex&amp;gt;ACABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;3+0=3&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_2=L_3=B&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=.&amp;lt;/tex&amp;gt;BACABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;1+4=5&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_2=L_5=A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=&amp;lt;/tex&amp;gt; ABACABA&lt;br /&gt;
&lt;br /&gt;
== Замечания ==&lt;br /&gt;
&lt;br /&gt;
* bzip2&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Bzip2 bzip2]&amp;lt;/ref&amp;gt; использует преобразование Барроуза {{---}} Уилера для превращения последовательностей многократно чередующихся символов в строки одинаковых символов, затем применяет преобразование [[Преобразование_MTF | MTF]], и в конце кодирование Хаффмана.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Алгоритм_Хаффмана | Алгоритм Хаффмана]]&lt;br /&gt;
* [[Алгоритмы_LZ77_и_LZ78 | Алгоритмы LZ77 и LZ78]]&lt;br /&gt;
* [[Арифметическое_кодирование | Арифметическое кодирование]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
*[http://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0_%E2%80%94_%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0 Википедия: Преобразование Барроуза {{---}} Уилера]&lt;br /&gt;
&lt;br /&gt;
*[http://www.cs.karelia.ru/~aborod/inf/2010/schedule.php.ru cs.karelia.ru: Преобразование Барроуза {{---}} Уилера]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы сжатия ]]&lt;/div&gt;</summary>
		<author><name>Evarand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0-%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0&amp;diff=50190</id>
		<title>Преобразование Барроуза-Уилера</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0-%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0&amp;diff=50190"/>
				<updated>2015-12-12T19:16:55Z</updated>
		
		<summary type="html">&lt;p&gt;Evarand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
'''Преобразование Барроуза {{---}} Уилера''' (англ. ''Burrows-Wheeler transform'') {{---}} алгоритм, используемый для предварительной обработки данных перед сжатием, разработанный для улучшения эффективности последующего кодирования. Преобразование Барроуза {{---}} Уилера меняет порядок символов во входной строке таким образом, что повторяющиеся подстроки образуют на выходе идущие подряд последовательности одинаковых символов.&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Преобразование выполняется в три этапа:&lt;br /&gt;
# Составляется таблица всех циклических сдвигов входной строки.&lt;br /&gt;
# Производится лексикографическая (в алфавитном порядке) сортировка строк таблицы.&lt;br /&gt;
# В качестве выходной строки выбирается последний столбец таблицы преобразования и номер строки, совпадающей с исходной.&lt;br /&gt;
&lt;br /&gt;
== Пример работы алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дана исходная строка &amp;lt;tex&amp;gt;$s =$&amp;lt;/tex&amp;gt; &amp;quot;ABACABA&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;4&amp;quot;|Трансформация&lt;br /&gt;
|-&lt;br /&gt;
! Вход || Все&amp;lt;br /&amp;gt;циклические &amp;lt;br /&amp;gt; сдвиги || Сортировка&amp;lt;br /&amp;gt;строк || Выход&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
BACABAA&amp;lt;br/&amp;gt;&lt;br /&gt;
ACABAAB&amp;lt;br/&amp;gt;&lt;br /&gt;
CABAABA&amp;lt;br/&amp;gt;&lt;br /&gt;
ABAABAC&amp;lt;br/&amp;gt;&lt;br /&gt;
BAABACA&amp;lt;br/&amp;gt;&lt;br /&gt;
AABACAB&amp;lt;br/&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
AABACAB&amp;lt;br/&amp;gt;&lt;br /&gt;
ABAABAC&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
ACABAAB&amp;lt;br/&amp;gt;&lt;br /&gt;
BAABACA&amp;lt;br/&amp;gt;&lt;br /&gt;
BACABAA&amp;lt;br/&amp;gt;&lt;br /&gt;
CABAABA &amp;lt;br/&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
BCABAAA, 3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Результат можно записать так: &amp;lt;tex&amp;gt;$BWT(s) = $(&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, &amp;lt;tex&amp;gt;3)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; {{---}} номер исходной строки в отсортированной матрице. Он нужен для обратного преобразования. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следует заметить, что иногда в исходной строке приводится так называемый символ конца строки &amp;lt;tex&amp;gt;\$&amp;lt;/tex&amp;gt;, который в преобразовании будет считаться последним (максимальным) символом, тогда сохранение номера исходной строки не требуется.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пусть нам дана исходная строка &amp;lt;tex&amp;gt;$s =$&amp;lt;/tex&amp;gt; &amp;quot;ABACABA$&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;4&amp;quot;|Трансформация&lt;br /&gt;
|-&lt;br /&gt;
! Вход || Все&amp;lt;br /&amp;gt;Перестановки || Сортировка&amp;lt;br /&amp;gt;Строк || Выход&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
BACABA$A&amp;lt;br/&amp;gt;&lt;br /&gt;
ACABA$AB&amp;lt;br/&amp;gt;&lt;br /&gt;
CABA$ABA&amp;lt;br/&amp;gt;&lt;br /&gt;
ABA$ABAC&amp;lt;br/&amp;gt;&lt;br /&gt;
BA$ABACA&amp;lt;br/&amp;gt;&lt;br /&gt;
A$ABACAB&amp;lt;br/&amp;gt;&lt;br /&gt;
$ABACABA&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
ABA$ABAC&amp;lt;br/&amp;gt;&lt;br /&gt;
ACABA$AB&amp;lt;br/&amp;gt;&lt;br /&gt;
A$ABACAB&amp;lt;br/&amp;gt;&lt;br /&gt;
BACABA$A&amp;lt;br/&amp;gt;&lt;br /&gt;
BA$ABACA&amp;lt;br/&amp;gt;&lt;br /&gt;
CABA$ABA &amp;lt;br/&amp;gt;&lt;br /&gt;
$ABACABA&lt;br /&gt;
|&lt;br /&gt;
$CBBAAAA&lt;br /&gt;
|} &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
При аналогичном вышеприведённом преобразовании та строчка в матрице, которая будет заканчиваться на символ конца строки, и будет исходной: (&amp;quot;ABACABA$&amp;quot;). Тогда результат можно записать так: &amp;lt;tex&amp;gt;$BWT(s) =$&amp;lt;/tex&amp;gt; &amp;quot;$CBBAAAA&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Обратное преобразование ==&lt;br /&gt;
&lt;br /&gt;
===Наивный алгоритм===&lt;br /&gt;
&lt;br /&gt;
Пусть нам дано: &amp;lt;tex&amp;gt;$BWT(s) =$(&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, &amp;lt;tex&amp;gt;3)&amp;lt;/tex&amp;gt;. Тогда выпишем в столбик нашу преобразованную последовательность символов &amp;quot;BCABAAA&amp;quot;. Запишем её как последний столбик предыдущей матрицы (при прямом преобразовании Барроуза {{---}} Уилера), при этом все предыдущие столбцы оставляем пустыми. Далее построчно [[Сортировки | отсортируем]] матрицу, затем в предыдущий столбец запишем &amp;quot;BCABAAA&amp;quot;. Опять построчно отсортируем матрицу. Продолжая таким образом, можно восстановить полный список всех циклических перестановок строки, которую нам надо найти. Выстроив полный отсортированный список перестановок, выберем строку с номером, который нам был изначально дан. В итоге мы получим искомую строку.&lt;br /&gt;
Алгоритм обратного преобразования описан в таблице ниже:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Обратное преобразование&lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Вход&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot; colspan=&amp;quot;8&amp;quot;|&lt;br /&gt;
BCABAAA&lt;br /&gt;
|-&lt;br /&gt;
! Добавление 1 || Сортировка 1 || Добавление 2 || Сортировка 2 || Добавление 3 || Сортировка 3 || Добавление 4 &lt;br /&gt;
|-align=&amp;quot;right&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
 B&lt;br /&gt;
 C&lt;br /&gt;
 A&lt;br /&gt;
 B&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
|&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 B&lt;br /&gt;
 B&lt;br /&gt;
 C&lt;br /&gt;
|&lt;br /&gt;
 BA&lt;br /&gt;
 CA&lt;br /&gt;
 AA&lt;br /&gt;
 BA&lt;br /&gt;
 AB&lt;br /&gt;
 AB&lt;br /&gt;
 AC&lt;br /&gt;
|&lt;br /&gt;
 AA&lt;br /&gt;
 AB&lt;br /&gt;
 AB&lt;br /&gt;
 AC&lt;br /&gt;
 BA&lt;br /&gt;
 BA&lt;br /&gt;
 CA&lt;br /&gt;
|&lt;br /&gt;
 BAA&lt;br /&gt;
 CAB&lt;br /&gt;
 AAB&lt;br /&gt;
 BAC&lt;br /&gt;
 ABA&lt;br /&gt;
 ABA&lt;br /&gt;
 ACA&lt;br /&gt;
|&lt;br /&gt;
 AAB&lt;br /&gt;
 ABA&lt;br /&gt;
 ABA&lt;br /&gt;
 ACA&lt;br /&gt;
 BAA&lt;br /&gt;
 BAC&lt;br /&gt;
 CAB&lt;br /&gt;
|&lt;br /&gt;
 BAAB&lt;br /&gt;
 CABA&lt;br /&gt;
 AABA&lt;br /&gt;
 BACA&lt;br /&gt;
 ABAA&lt;br /&gt;
 ABAC&lt;br /&gt;
 ACAB&lt;br /&gt;
|-&lt;br /&gt;
! Сортировка 4 || Добавление 5 || Сортировка 5 || Добавление 6 || Сортировка 6 || Добавление 7 || Сортировка 7&lt;br /&gt;
&lt;br /&gt;
|-align=&amp;quot;right&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
 AABA&lt;br /&gt;
 ABAA&lt;br /&gt;
 ABAC&lt;br /&gt;
 ACAB&lt;br /&gt;
 BAAB&lt;br /&gt;
 BACA&lt;br /&gt;
 CABA&lt;br /&gt;
|&lt;br /&gt;
 BAABA&lt;br /&gt;
 CABAA&lt;br /&gt;
 AABAC&lt;br /&gt;
 BACAB&lt;br /&gt;
 ABAAB&lt;br /&gt;
 ABACA&lt;br /&gt;
 ACABA&lt;br /&gt;
|&lt;br /&gt;
 AABAC&lt;br /&gt;
 ABAAB&lt;br /&gt;
 ABACA&lt;br /&gt;
 ACABA&lt;br /&gt;
 BAABA&lt;br /&gt;
 BACAB&lt;br /&gt;
 CABAA&lt;br /&gt;
|&lt;br /&gt;
 BAABAC&lt;br /&gt;
 CABAAB&lt;br /&gt;
 AABACA&lt;br /&gt;
 BACABA&lt;br /&gt;
 ABAABA&lt;br /&gt;
 ABACAB&lt;br /&gt;
 ACABAA&lt;br /&gt;
|&lt;br /&gt;
 AABACA&lt;br /&gt;
 ABAABA&lt;br /&gt;
 ABACAB&lt;br /&gt;
 ACABAA&lt;br /&gt;
 BAABAC&lt;br /&gt;
 BACABA&lt;br /&gt;
 CABAAB&lt;br /&gt;
|&lt;br /&gt;
 BAABACA&lt;br /&gt;
 CABAABA&lt;br /&gt;
 AABACAB&lt;br /&gt;
 BACABAA&lt;br /&gt;
 ABAABAC&lt;br /&gt;
 ABACABA&lt;br /&gt;
 ACABAAB&lt;br /&gt;
|&lt;br /&gt;
 AABACAB&lt;br /&gt;
 ABAABAC&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
 ACABAAB&lt;br /&gt;
 BAABACA&lt;br /&gt;
 BACABAA&lt;br /&gt;
 CABAABA&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Результат&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot; colspan=&amp;quot;8&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Следует также заметить, что если нам было бы дано &amp;lt;tex&amp;gt;$BWT(s) = $&amp;lt;/tex&amp;gt; &amp;quot;$CBBAAAA&amp;quot;, то мы также получили бы нашу исходную строку, только с символом конца строки &amp;lt;tex&amp;gt;\$&amp;lt;/tex&amp;gt; на конце: ABACABA$.&lt;br /&gt;
&lt;br /&gt;
Временная сложность данного алгоритма &amp;lt;tex&amp;gt;O(N^3\log{N}) &amp;lt;/tex&amp;gt;, пространственная &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Доказательство корректности====&lt;br /&gt;
&lt;br /&gt;
Пусть дана строка &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;, к которой было применено преобразование BWT. Докажем, что при использовании наивного алгоритма на каждом шаге получающийся набор строк соответствует суффиксам циклических перестановок исходной строки, методом математической индукции.&lt;br /&gt;
* '''База'''. Циклически сдвинем все строки исходной таблицы на &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; влево. Тогда в столбце &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; будут находиться символы, добавленные на первом шаге алгоритма, а в столбце &amp;lt;tex&amp;gt;n - 1&amp;lt;/tex&amp;gt; символы, изначально стоявшие в таблице до первого шага алгоритма. Таким образом, полученные на первом шаге алгоритма строки являются суффиксами циклических перестановок строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* '''Предположение'''. Пусть на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; шаге алгоритма все полученные строки являются суффиксами циклических перестановок строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* '''Переход'''. Рассмотрим &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ый шаг алгоритма. Все строки отсортированы, поэтому самый левый столбец совпадет с &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; столбцом исходной таблицы. Циклически сдвинем все строки исходной таблицы на &amp;lt;tex&amp;gt;n - k&amp;lt;/tex&amp;gt; символов вправо. Теперь по предположению первые &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; символов справа в каждой строке совпадают у исходной таблицы и у таблицы, полученной в результате работы алгоритма. &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;-ые справа столбцы также совпадают. Добавленный на &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ом шаге столбец также совпадает с &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ым справа столбцом сдвинутой исходной таблицы, так как совпадает с последним столбцом исходной таблицы, которая была сдвинута на &amp;lt;tex&amp;gt;n-k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;3&amp;quot; | &amp;lt;tex&amp;gt;$k+1$&amp;lt;/tex&amp;gt; шаг алгоритма при &amp;lt;tex&amp;gt;$k=3$&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! Исходная &amp;lt;br /&amp;gt; таблица || Сдвинутая &amp;lt;br /&amp;gt; таблица || Результат &amp;lt;br /&amp;gt; работы &amp;lt;br /&amp;gt; алгоритма&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;CA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt;BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt;AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt;AA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt;AC&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt;BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
CA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
AA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
AC&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:right;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Таким образом, поскольку на каждом шаге алгоритма получившиеся строки являлись суффиксами циклических перестановок &amp;lt;tex&amp;gt; $s$ &amp;lt;/tex&amp;gt;, после последнего шага получившиеся строки будут совпадать с циклическими перестановками &amp;lt;tex&amp;gt; $s$ &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Оптимизированный наивный алгоритм===&lt;br /&gt;
&lt;br /&gt;
Наивный алгоритм можно оптимизировать. Заметим, что при каждом проявлении неизвестного столбца выполнялись одни и те же действия. Мы приписывали новый столбец и сортировали имеющиеся данные. На каждом шагу мы к строке, которая находилась на &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;-ом месте приписываем в начало &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; -ый элемент столбца входных данных. Пусть изначально мы знаем каким по порядку является приписанный нами в начало символ (то есть каким по порядку в столбце). И конечно же мы знаем исходя из предыдущего шага какое место занимала наша строка без этого первого символа (&amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; -ое). Тогда несложно заметить, что при выполнении такой операции строка с номером &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; всегда будет перемещаться на позицию с номером &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |0||а||&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;||р||9&lt;br /&gt;
  |-&lt;br /&gt;
  |1||а||||д||7&lt;br /&gt;
  |-&lt;br /&gt;
  |2||а|| ||a||0&lt;br /&gt;
  |-&lt;br /&gt;
  |3||а|| ||к||8&lt;br /&gt;
  |-&lt;br /&gt;
  |4||а|| ||р||10&lt;br /&gt;
  |-&lt;br /&gt;
  |5||б|| ||a||1&lt;br /&gt;
  |-&lt;br /&gt;
  |6||б|| ||a||2&lt;br /&gt;
  |-&lt;br /&gt;
  |7||д|| ||a||3&lt;br /&gt;
  |-&lt;br /&gt;
  |8||к|| ||a||4&lt;br /&gt;
  |-&lt;br /&gt;
  |9||р|| ||б||5&lt;br /&gt;
  |-&lt;br /&gt;
  |10||р|| ||б||6&lt;br /&gt;
  |}&lt;br /&gt;
&lt;br /&gt;
Здесь слева отсортированный данный столбец, чтобы мы знали, какое место в лексикографическом порядке занимает приписываемый нами символ среди всех элементов данного нам изначально столбца. Справа - изначально данный столбец и соответствующее ему число. Поскольку в нашем алгоритме новый столбец приписывается в начало, то мы из состояния &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; (левый столбец) переходим в состояние &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; (правый). Для того, чтобы восстановить строку, нам необходимо от последней такой цифры по пути из &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; восстановить строку.&lt;br /&gt;
{|&lt;br /&gt;
 |&lt;br /&gt;
 {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
 |6&lt;br /&gt;
 |→&lt;br /&gt;
 |10&lt;br /&gt;
 |→&lt;br /&gt;
 |4 &lt;br /&gt;
 |→&lt;br /&gt;
 |8&lt;br /&gt;
 |→ &lt;br /&gt;
 |3&lt;br /&gt;
 |→&lt;br /&gt;
 |7&lt;br /&gt;
 |→&lt;br /&gt;
 |1&lt;br /&gt;
 |→&lt;br /&gt;
 |5&lt;br /&gt;
 |→&lt;br /&gt;
 |9&lt;br /&gt;
 |→&lt;br /&gt;
 |0&lt;br /&gt;
 |→&lt;br /&gt;
 |2&lt;br /&gt;
 |-&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |б&lt;br /&gt;
 |&lt;br /&gt;
 |р&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |к&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |д&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |б&lt;br /&gt;
 |&lt;br /&gt;
 |р&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
|}&lt;br /&gt;
====Сложность оптимизированного алгоритма====&lt;br /&gt;
Данный алгоритм работает за &amp;lt;tex&amp;gt;O(N\log{N})&amp;lt;/tex&amp;gt; времени и требует &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt; памяти. Однако, если размер алфавита не очень большой, то для выяснения первого столбца матрицы можно использовать сортировку подсчетом, в этом случае алгоритм работает за &amp;lt;tex&amp;gt;O(N+M)&amp;lt;/tex&amp;gt; действий и требует &amp;lt;tex&amp;gt;O(N+M)&amp;lt;/tex&amp;gt; памяти, где &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; — размер алфавита.&lt;br /&gt;
&lt;br /&gt;
====Псевдокод оптимизированного алгоритма====&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; N &amp;lt;/tex&amp;gt; — количество символов во входной строке, &amp;lt;tex&amp;gt; M &amp;lt;/tex&amp;gt; — количество символов в алфавите, &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; — номер исходной строки в матрице перестановок, &amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt; — входящая строка, &amp;lt;tex&amp;gt; count &amp;lt;/tex&amp;gt;  — массив для сортировки подсчетом, &amp;lt;tex&amp;gt; t &amp;lt;/tex&amp;gt; — вектор обратного преобразования, &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; — номер данной нам строки в таблице.&lt;br /&gt;
&lt;br /&gt;
  '''function''' reverseBWT(N : Int, M : Int, k : Int, s : String): Int[]&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Cчитаем частоты символов&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' i = 0 .. M &lt;br /&gt;
      count[i] = 0&lt;br /&gt;
    '''for''' i = 0 .. N &lt;br /&gt;
      count[s[i]]++&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Упорядочиваем символы, чтобы получить первый столбец исходной матрицы&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// count[i] указывает на первую позицию символа i в первом столбце&amp;lt;/font&amp;gt;&lt;br /&gt;
    sum = 0&lt;br /&gt;
    '''for''' i = 0 .. M&lt;br /&gt;
      sum = sum + count[i]&lt;br /&gt;
      count[i] = sum - count[i]&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Cоздаем вектор обратного преобразования&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' i = 0 .. N&lt;br /&gt;
    t[count[s[i]]] = i&lt;br /&gt;
    count[s[i]]++&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// И восстанавливаем исходный текст&amp;lt;/font&amp;gt;&lt;br /&gt;
    j = t[x]&lt;br /&gt;
    '''for''' i = 0 .. N&lt;br /&gt;
      answer[i] = s[j]&lt;br /&gt;
      j = t[j]&lt;br /&gt;
    '''return''' answer&lt;br /&gt;
&lt;br /&gt;
====Доказательство корректности====&lt;br /&gt;
&lt;br /&gt;
Пусть текст &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; состоит из &amp;lt;tex&amp;gt;N + 1&amp;lt;/tex&amp;gt; символов, занумерованных с нуля: &amp;lt;tex&amp;gt;T[0..N]&amp;lt;/tex&amp;gt;. Буквы &amp;lt;tex&amp;gt;T[i]&amp;lt;/tex&amp;gt; принадлежат некоторому алфавиту &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Лексикографический порядок (строгий) на строках из алфавита &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; будем обозначать &amp;lt;tex&amp;gt;\preceq (\prec)&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt;S_{k}T&amp;lt;/tex&amp;gt; циклический сдвиг текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; символов влево:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt; S_{k}T = T[(j + k) (\bmod\ N + 1)] &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Существует перестановка &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;\{0, ..., N\}&amp;lt;/tex&amp;gt;, которая удовлетворяет условию: &lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt; S_{p(i)}T \preceq S_{p(i + 1)}T,\ i = 0, ..., N - 1\ \ \textbf{(1)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Преобразование Барроуза-Уилера текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; есть текст &amp;lt;tex&amp;gt;B[0..N] = BW(T)&amp;lt;/tex&amp;gt;, буквы которого заданы соотношением:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt;B[i] = S_{p(i)}T[N]&amp;lt;/tex&amp;gt;, другими словами &amp;lt;tex&amp;gt;B[i] = S_{p(i) - 1}T[0] = T[(p(i) - 1) (\bmod\ N + 1)] \ \ \textbf{(2)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} перестановка чисел &amp;lt;tex&amp;gt;\{0, ..., N\}&amp;lt;/tex&amp;gt;, удовлетворяющая условию:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt;B_{\sigma(i)} \preceq B_{\sigma(i + 1)}&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N - 1\ \ \textbf{(3)}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
|}&lt;br /&gt;
и в случае равенства &amp;lt;tex&amp;gt;B_{\sigma(i)}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;B_{\sigma(i + 1)}&amp;lt;/tex&amp;gt; выполнено {{---}} &amp;lt;tex&amp;gt;\sigma(i) &amp;lt; \sigma(i + 1)&amp;lt;/tex&amp;gt;. Перестановка однозначно определяется текстом &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; и ее можно посчитать за &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt;, используя сортировку подсчетом. Рассмотрим перестановку &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; как отображение &amp;lt;tex&amp;gt;\sigma : \{0, ..., N\} \to \{0, ..., N\}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;\sigma^{k}&amp;lt;/tex&amp;gt; копмозиция &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; отображений &amp;lt;tex&amp;gt;\sigma^{k} = \sigma^{k - 1} \circ \sigma&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\sigma^{1} = \sigma, \sigma^{0} \equiv i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
&lt;br /&gt;
''При всех &amp;lt;tex&amp;gt;m = 1, ..., N + 1&amp;lt;/tex&amp;gt; верны утверждения,&lt;br /&gt;
:&amp;lt;tex&amp;gt;B_{\sigma(i)}...B_{\sigma^{m}(i)} \preceq B_{\sigma(i + 1)}...B_{\sigma^{m}(i + 1)}&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N - 1\ \ \textbf{(4)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;B_iB_{\sigma(i)}...B_{\sigma^{m - 1}(i)} = S_{p(i) - 1}T[0..m - 1]&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N\ \ \textbf{(5)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
|proof=&lt;br /&gt;
&lt;br /&gt;
Если лексикографически отсортировать буквы последнего столбца и поместить их в первый столбец, то получится таблица&lt;br /&gt;
&lt;br /&gt;
| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Таблица&lt;br /&gt;
|-&lt;br /&gt;
|a||b||c&lt;br /&gt;
|-&lt;br /&gt;
|a||b||c&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
&lt;br /&gt;
''Для восстановления исходного текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из преобразования &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; достаточно знать число &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;, отвечающее условию &amp;lt;tex&amp;gt;p(I) = 0&amp;lt;/tex&amp;gt;, другими словами &amp;lt;tex&amp;gt;S_{p(I)}T = T&amp;lt;/tex&amp;gt;.''&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Алгоритм за линейное время===&lt;br /&gt;
&lt;br /&gt;
Будем обозначать &amp;lt;tex&amp;gt;s^i&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ую циклическую перестановку &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;s^0 = s_0 s_1 \ldots s_{n-1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;$BWT(s)$\;= L&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;L = L_0L_1\ldots L_{n-1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; -- номер строки &amp;lt;tex&amp;gt;s^0&amp;lt;/tex&amp;gt; в таблице. Предподсчитаем следующие величины:&lt;br /&gt;
* Для каждого &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt; количество символов на подстроке &amp;lt;tex&amp;gt;l_0, \ldots , l_{i-1}&amp;lt;/tex&amp;gt;, равных &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
* Для каждого уникального &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt; количество символов в &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;, лексикографически меньших, чем &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пример для &amp;lt;tex&amp;gt;$BWT(s) =$&amp;lt;/tex&amp;gt; &amp;quot;BCABAAA&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
!colspan=&amp;quot;3&amp;quot; | Таблица первого предподсчёта&lt;br /&gt;
|-&lt;br /&gt;
! Позиция || Символ || Результат&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
! 0 || B || 0&lt;br /&gt;
|-&lt;br /&gt;
! 1 || C || 0&lt;br /&gt;
|-&lt;br /&gt;
! 2 || A || 0&lt;br /&gt;
|-&lt;br /&gt;
! 3 || B || 1&lt;br /&gt;
|-&lt;br /&gt;
! 4 || A || 1&lt;br /&gt;
|-&lt;br /&gt;
! 5 || A || 2&lt;br /&gt;
|-&lt;br /&gt;
! 6 || A || 3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; | Таблица второго предподсчёта&lt;br /&gt;
|-&lt;br /&gt;
! Символ || Количество  &amp;lt;br /&amp;gt; меньших&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
! A || 0&lt;br /&gt;
|-&lt;br /&gt;
! B || 4&lt;br /&gt;
|-&lt;br /&gt;
! C || 6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Для удобства пронумеруем известные нам данные:&lt;br /&gt;
# &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;, последний столбец таблицы перестановок&lt;br /&gt;
# &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;, номер строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt; в таблице перестановок&lt;br /&gt;
# Частота, с которой символ &amp;lt;tex&amp;gt;L_{i}&amp;lt;/tex&amp;gt; встречается в подстроке &amp;lt;tex&amp;gt;l_0, \ldots , l_{i-1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
# Для каждого уникального символа количество лексикографически меньших символов в &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Символ &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt; находится в строке &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; под номером &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;, так как в таблице строка &amp;lt;tex&amp;gt;s^0&amp;lt;/tex&amp;gt; имела номер &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;. Найдём символ &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Символ &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt; имеет в строке &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; тот же номер, что строка &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt; имела в таблице перестановок: строка &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt; начинается с символа &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt; находится на 1 левее его и из-за циклического сдвига оказывается в последнем столбце. Нам известен символ &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;. Посчитаем, на каком месте в таблице будет стоять строка, начинающаяся с этого символа.&lt;br /&gt;
&lt;br /&gt;
Из 4 известно количество символов, меньших &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;. Все строки, начинающиеся с этих символов, стоят в таблице раньше &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt;. Кроме того, в таблице есть строки, начинающиеся с того же символа, что и &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt;. Из 3 известно, сколько их: если символ, равный &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, встречался в &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; раньше, чем &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, то в таблице строка, начинающаяся с этого символа, тоже стоит раньше строки, начинающейся с &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, так как префикс строки, оканчивающейся на этот символ, меньше префикса строки, оканчивающейся на &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Тогда сумма этих двух величин является номером символа &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt; в строке &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;. Зная &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt;, аналогично найдём &amp;lt;tex&amp;gt;s_{n-3}\ldots s_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предподсчёт занимает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени, восстановление каждого из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; символов занимает &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; времени. Суммарное время работы алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пример работы для &amp;lt;tex&amp;gt;$BWT(s) = ($&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, 2&amp;lt;tex&amp;gt;)&amp;lt;/tex&amp;gt; (нумерация с 0):&lt;br /&gt;
* &amp;lt;tex&amp;gt;s^0 = .......&amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;s_6=L_2 = A&amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt;s^0=......&amp;lt;/tex&amp;gt;A&lt;br /&gt;
* Суммируем значения из двух таблиц: &amp;lt;tex&amp;gt;0+0=0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_5=L_0=B&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=.....&amp;lt;/tex&amp;gt;BA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;0+4=4&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_4=L_4=A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=....&amp;lt;/tex&amp;gt;ABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;1+0=1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_3=L_1=C&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=...&amp;lt;/tex&amp;gt;CABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;0+6=6&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_2=L_6=A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=..&amp;lt;/tex&amp;gt;ACABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;3+0=3&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_2=L_3=B&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=.&amp;lt;/tex&amp;gt;BACABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;1+4=5&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_2=L_5=A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=&amp;lt;/tex&amp;gt; ABACABA&lt;br /&gt;
&lt;br /&gt;
== Дополнительно ==&lt;br /&gt;
&lt;br /&gt;
* bzip2&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Bzip2 bzip2]&amp;lt;/ref&amp;gt; использует преобразование Барроуза {{---}} Уилера для превращения последовательностей многократно чередующихся символов в строки одинаковых символов, затем применяет преобразование [[Преобразование_MTF | MTF]], и в конце кодирование Хаффмана.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Алгоритм_Хаффмана | Алгоритм Хаффмана]]&lt;br /&gt;
* [[Алгоритмы_LZ77_и_LZ78 | Алгоритмы LZ77 и LZ78]]&lt;br /&gt;
* [[Арифметическое_кодирование | Арифметическое кодирование]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
*[http://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0_%E2%80%94_%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0 Википедия: Преобразование Барроуза {{---}} Уилера]&lt;br /&gt;
&lt;br /&gt;
*[http://www.cs.karelia.ru/~aborod/inf/2010/schedule.php.ru cs.karelia.ru: Преобразование Барроуза {{---}} Уилера]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы сжатия ]]&lt;/div&gt;</summary>
		<author><name>Evarand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0-%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0&amp;diff=50189</id>
		<title>Преобразование Барроуза-Уилера</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0-%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0&amp;diff=50189"/>
				<updated>2015-12-12T19:16:19Z</updated>
		
		<summary type="html">&lt;p&gt;Evarand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
'''Преобразование Барроуза {{---}} Уилера''' (англ. ''Burrows-Wheeler transform'') {{---}} алгоритм, используемый для предварительной обработки данных перед сжатием, разработанный для улучшения эффективности последующего кодирования. Преобразование Барроуза {{---}} Уилера меняет порядок символов во входной строке таким образом, что повторяющиеся подстроки образуют на выходе идущие подряд последовательности одинаковых символов.&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Преобразование выполняется в три этапа:&lt;br /&gt;
# Составляется таблица всех циклических сдвигов входной строки.&lt;br /&gt;
# Производится лексикографическая (в алфавитном порядке) сортировка строк таблицы.&lt;br /&gt;
# В качестве выходной строки выбирается последний столбец таблицы преобразования и номер строки, совпадающей с исходной.&lt;br /&gt;
&lt;br /&gt;
== Пример работы алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дана исходная строка &amp;lt;tex&amp;gt;$s =$&amp;lt;/tex&amp;gt; &amp;quot;ABACABA&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;4&amp;quot;|Трансформация&lt;br /&gt;
|-&lt;br /&gt;
! Вход || Все&amp;lt;br /&amp;gt;циклические &amp;lt;br /&amp;gt; сдвиги || Сортировка&amp;lt;br /&amp;gt;строк || Выход&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
BACABAA&amp;lt;br/&amp;gt;&lt;br /&gt;
ACABAAB&amp;lt;br/&amp;gt;&lt;br /&gt;
CABAABA&amp;lt;br/&amp;gt;&lt;br /&gt;
ABAABAC&amp;lt;br/&amp;gt;&lt;br /&gt;
BAABACA&amp;lt;br/&amp;gt;&lt;br /&gt;
AABACAB&amp;lt;br/&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
AABACAB&amp;lt;br/&amp;gt;&lt;br /&gt;
ABAABAC&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
ACABAAB&amp;lt;br/&amp;gt;&lt;br /&gt;
BAABACA&amp;lt;br/&amp;gt;&lt;br /&gt;
BACABAA&amp;lt;br/&amp;gt;&lt;br /&gt;
CABAABA &amp;lt;br/&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
BCABAAA, 3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Результат можно записать так: &amp;lt;tex&amp;gt;$BWT(s) = $(&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, &amp;lt;tex&amp;gt;3)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; {{---}} номер исходной строки в отсортированной матрице. Он нужен для обратного преобразования. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следует заметить, что иногда в исходной строке приводится так называемый символ конца строки &amp;lt;tex&amp;gt;\$&amp;lt;/tex&amp;gt;, который в преобразовании будет считаться последним (максимальным) символом, тогда сохранение номера исходной строки не требуется.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пусть нам дана исходная строка &amp;lt;tex&amp;gt;$s =$&amp;lt;/tex&amp;gt; &amp;quot;ABACABA$&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;4&amp;quot;|Трансформация&lt;br /&gt;
|-&lt;br /&gt;
! Вход || Все&amp;lt;br /&amp;gt;Перестановки || Сортировка&amp;lt;br /&amp;gt;Строк || Выход&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
BACABA$A&amp;lt;br/&amp;gt;&lt;br /&gt;
ACABA$AB&amp;lt;br/&amp;gt;&lt;br /&gt;
CABA$ABA&amp;lt;br/&amp;gt;&lt;br /&gt;
ABA$ABAC&amp;lt;br/&amp;gt;&lt;br /&gt;
BA$ABACA&amp;lt;br/&amp;gt;&lt;br /&gt;
A$ABACAB&amp;lt;br/&amp;gt;&lt;br /&gt;
$ABACABA&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
ABA$ABAC&amp;lt;br/&amp;gt;&lt;br /&gt;
ACABA$AB&amp;lt;br/&amp;gt;&lt;br /&gt;
A$ABACAB&amp;lt;br/&amp;gt;&lt;br /&gt;
BACABA$A&amp;lt;br/&amp;gt;&lt;br /&gt;
BA$ABACA&amp;lt;br/&amp;gt;&lt;br /&gt;
CABA$ABA &amp;lt;br/&amp;gt;&lt;br /&gt;
$ABACABA&lt;br /&gt;
|&lt;br /&gt;
$CBBAAAA&lt;br /&gt;
|} &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
При аналогичном вышеприведённом преобразовании та строчка в матрице, которая будет заканчиваться на символ конца строки, и будет исходной: (&amp;quot;ABACABA$&amp;quot;). Тогда результат можно записать так: &amp;lt;tex&amp;gt;$BWT(s) =$&amp;lt;/tex&amp;gt; &amp;quot;$CBBAAAA&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Обратное преобразование ==&lt;br /&gt;
&lt;br /&gt;
===Наивный алгоритм===&lt;br /&gt;
&lt;br /&gt;
Пусть нам дано: &amp;lt;tex&amp;gt;$BWT(s) =$(&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, &amp;lt;tex&amp;gt;3)&amp;lt;/tex&amp;gt;. Тогда выпишем в столбик нашу преобразованную последовательность символов &amp;quot;BCABAAA&amp;quot;. Запишем её как последний столбик предыдущей матрицы (при прямом преобразовании Барроуза {{---}} Уилера), при этом все предыдущие столбцы оставляем пустыми. Далее построчно [[Сортировки | отсортируем]] матрицу, затем в предыдущий столбец запишем &amp;quot;BCABAAA&amp;quot;. Опять построчно отсортируем матрицу. Продолжая таким образом, можно восстановить полный список всех циклических перестановок строки, которую нам надо найти. Выстроив полный отсортированный список перестановок, выберем строку с номером, который нам был изначально дан. В итоге мы получим искомую строку.&lt;br /&gt;
Алгоритм обратного преобразования описан в таблице ниже:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Обратное преобразование&lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Вход&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot; colspan=&amp;quot;8&amp;quot;|&lt;br /&gt;
BCABAAA&lt;br /&gt;
|-&lt;br /&gt;
! Добавление 1 || Сортировка 1 || Добавление 2 || Сортировка 2 || Добавление 3 || Сортировка 3 || Добавление 4 &lt;br /&gt;
|-align=&amp;quot;right&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
 B&lt;br /&gt;
 C&lt;br /&gt;
 A&lt;br /&gt;
 B&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
|&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 B&lt;br /&gt;
 B&lt;br /&gt;
 C&lt;br /&gt;
|&lt;br /&gt;
 BA&lt;br /&gt;
 CA&lt;br /&gt;
 AA&lt;br /&gt;
 BA&lt;br /&gt;
 AB&lt;br /&gt;
 AB&lt;br /&gt;
 AC&lt;br /&gt;
|&lt;br /&gt;
 AA&lt;br /&gt;
 AB&lt;br /&gt;
 AB&lt;br /&gt;
 AC&lt;br /&gt;
 BA&lt;br /&gt;
 BA&lt;br /&gt;
 CA&lt;br /&gt;
|&lt;br /&gt;
 BAA&lt;br /&gt;
 CAB&lt;br /&gt;
 AAB&lt;br /&gt;
 BAC&lt;br /&gt;
 ABA&lt;br /&gt;
 ABA&lt;br /&gt;
 ACA&lt;br /&gt;
|&lt;br /&gt;
 AAB&lt;br /&gt;
 ABA&lt;br /&gt;
 ABA&lt;br /&gt;
 ACA&lt;br /&gt;
 BAA&lt;br /&gt;
 BAC&lt;br /&gt;
 CAB&lt;br /&gt;
|&lt;br /&gt;
 BAAB&lt;br /&gt;
 CABA&lt;br /&gt;
 AABA&lt;br /&gt;
 BACA&lt;br /&gt;
 ABAA&lt;br /&gt;
 ABAC&lt;br /&gt;
 ACAB&lt;br /&gt;
|-&lt;br /&gt;
! Сортировка 4 || Добавление 5 || Сортировка 5 || Добавление 6 || Сортировка 6 || Добавление 7 || Сортировка 7&lt;br /&gt;
&lt;br /&gt;
|-align=&amp;quot;right&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
 AABA&lt;br /&gt;
 ABAA&lt;br /&gt;
 ABAC&lt;br /&gt;
 ACAB&lt;br /&gt;
 BAAB&lt;br /&gt;
 BACA&lt;br /&gt;
 CABA&lt;br /&gt;
|&lt;br /&gt;
 BAABA&lt;br /&gt;
 CABAA&lt;br /&gt;
 AABAC&lt;br /&gt;
 BACAB&lt;br /&gt;
 ABAAB&lt;br /&gt;
 ABACA&lt;br /&gt;
 ACABA&lt;br /&gt;
|&lt;br /&gt;
 AABAC&lt;br /&gt;
 ABAAB&lt;br /&gt;
 ABACA&lt;br /&gt;
 ACABA&lt;br /&gt;
 BAABA&lt;br /&gt;
 BACAB&lt;br /&gt;
 CABAA&lt;br /&gt;
|&lt;br /&gt;
 BAABAC&lt;br /&gt;
 CABAAB&lt;br /&gt;
 AABACA&lt;br /&gt;
 BACABA&lt;br /&gt;
 ABAABA&lt;br /&gt;
 ABACAB&lt;br /&gt;
 ACABAA&lt;br /&gt;
|&lt;br /&gt;
 AABACA&lt;br /&gt;
 ABAABA&lt;br /&gt;
 ABACAB&lt;br /&gt;
 ACABAA&lt;br /&gt;
 BAABAC&lt;br /&gt;
 BACABA&lt;br /&gt;
 CABAAB&lt;br /&gt;
|&lt;br /&gt;
 BAABACA&lt;br /&gt;
 CABAABA&lt;br /&gt;
 AABACAB&lt;br /&gt;
 BACABAA&lt;br /&gt;
 ABAABAC&lt;br /&gt;
 ABACABA&lt;br /&gt;
 ACABAAB&lt;br /&gt;
|&lt;br /&gt;
 AABACAB&lt;br /&gt;
 ABAABAC&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
 ACABAAB&lt;br /&gt;
 BAABACA&lt;br /&gt;
 BACABAA&lt;br /&gt;
 CABAABA&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Результат&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot; colspan=&amp;quot;8&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Следует также заметить, что если нам было бы дано &amp;lt;tex&amp;gt;$BWT(s) = $&amp;lt;/tex&amp;gt; &amp;quot;$CBBAAAA&amp;quot;, то мы также получили бы нашу исходную строку, только с символом конца строки &amp;lt;tex&amp;gt;\$&amp;lt;/tex&amp;gt; на конце: ABACABA$.&lt;br /&gt;
&lt;br /&gt;
Временная сложность данного алгоритма &amp;lt;tex&amp;gt;O(N^3\log{N}) &amp;lt;/tex&amp;gt;, пространственная &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Доказательство корректности====&lt;br /&gt;
&lt;br /&gt;
Пусть дана строка &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;, к которой было применено преобразование BWT. Докажем, что при использовании наивного алгоритма на каждом шаге получающийся набор строк соответствует суффиксам циклических перестановок исходной строки, методом математической индукции.&lt;br /&gt;
* '''База'''. Циклически сдвинем все строки исходной таблицы на &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; влево. Тогда в столбце &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; будут находиться символы, добавленные на первом шаге алгоритма, а в столбце &amp;lt;tex&amp;gt;n - 1&amp;lt;/tex&amp;gt; символы, изначально стоявшие в таблице до первого шага алгоритма. Таким образом, полученные на первом шаге алгоритма строки являются суффиксами циклических перестановок строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* '''Предположение'''. Пусть на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; шаге алгоритма все полученные строки являются суффиксами циклических перестановок строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* '''Переход'''. Рассмотрим &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ый шаг алгоритма. Все строки отсортированы, поэтому самый левый столбец совпадет с &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; столбцом исходной таблицы. Циклически сдвинем все строки исходной таблицы на &amp;lt;tex&amp;gt;n - k&amp;lt;/tex&amp;gt; символов вправо. Теперь по предположению первые &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; символов справа в каждой строке совпадают у исходной таблицы и у таблицы, полученной в результате работы алгоритма. &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;-ые справа столбцы также совпадают. Добавленный на &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ом шаге столбец также совпадает с &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ым справа столбцом сдвинутой исходной таблицы, так как совпадает с последним столбцом исходной таблицы, которая была сдвинута на &amp;lt;tex&amp;gt;n-k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;3&amp;quot; | &amp;lt;tex&amp;gt;$k+1$&amp;lt;/tex&amp;gt; шаг алгоритма при &amp;lt;tex&amp;gt;$k=3$&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! Исходная &amp;lt;br /&amp;gt; таблица || Сдвинутая &amp;lt;br /&amp;gt; таблица || Результат &amp;lt;br /&amp;gt; работы &amp;lt;br /&amp;gt; алгоритма&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;CA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt;BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt;AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt;AA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt;AC&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt;BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
CA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
AA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
AC&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:right;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Таким образом, поскольку на каждом шаге алгоритма получившиеся строки являлись суффиксами циклических перестановок &amp;lt;tex&amp;gt; $s$ &amp;lt;/tex&amp;gt;, после последнего шага получившиеся строки будут совпадать с циклическими перестановками &amp;lt;tex&amp;gt; $s$ &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Оптимизированный наивный алгоритм===&lt;br /&gt;
&lt;br /&gt;
Наивный алгоритм можно оптимизировать. Заметим, что при каждом проявлении неизвестного столбца выполнялись одни и те же действия. Мы приписывали новый столбец и сортировали имеющиеся данные. На каждом шагу мы к строке, которая находилась на &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;-ом месте приписываем в начало &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; -ый элемент столбца входных данных. Пусть изначально мы знаем каким по порядку является приписанный нами в начало символ (то есть каким по порядку в столбце). И конечно же мы знаем исходя из предыдущего шага какое место занимала наша строка без этого первого символа (&amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; -ое). Тогда несложно заметить, что при выполнении такой операции строка с номером &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; всегда будет перемещаться на позицию с номером &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |0||а||&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;||р||9&lt;br /&gt;
  |-&lt;br /&gt;
  |1||а||||д||7&lt;br /&gt;
  |-&lt;br /&gt;
  |2||а|| ||a||0&lt;br /&gt;
  |-&lt;br /&gt;
  |3||а|| ||к||8&lt;br /&gt;
  |-&lt;br /&gt;
  |4||а|| ||р||10&lt;br /&gt;
  |-&lt;br /&gt;
  |5||б|| ||a||1&lt;br /&gt;
  |-&lt;br /&gt;
  |6||б|| ||a||2&lt;br /&gt;
  |-&lt;br /&gt;
  |7||д|| ||a||3&lt;br /&gt;
  |-&lt;br /&gt;
  |8||к|| ||a||4&lt;br /&gt;
  |-&lt;br /&gt;
  |9||р|| ||б||5&lt;br /&gt;
  |-&lt;br /&gt;
  |10||р|| ||б||6&lt;br /&gt;
  |}&lt;br /&gt;
&lt;br /&gt;
Здесь слева отсортированный данный столбец, чтобы мы знали, какое место в лексикографическом порядке занимает приписываемый нами символ среди всех элементов данного нам изначально столбца. Справа - изначально данный столбец и соответствующее ему число. Поскольку в нашем алгоритме новый столбец приписывается в начало, то мы из состояния &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; (левый столбец) переходим в состояние &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; (правый). Для того, чтобы восстановить строку, нам необходимо от последней такой цифры по пути из &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; восстановить строку.&lt;br /&gt;
{|&lt;br /&gt;
 |&lt;br /&gt;
 {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
 |6&lt;br /&gt;
 |→&lt;br /&gt;
 |10&lt;br /&gt;
 |→&lt;br /&gt;
 |4 &lt;br /&gt;
 |→&lt;br /&gt;
 |8&lt;br /&gt;
 |→ &lt;br /&gt;
 |3&lt;br /&gt;
 |→&lt;br /&gt;
 |7&lt;br /&gt;
 |→&lt;br /&gt;
 |1&lt;br /&gt;
 |→&lt;br /&gt;
 |5&lt;br /&gt;
 |→&lt;br /&gt;
 |9&lt;br /&gt;
 |→&lt;br /&gt;
 |0&lt;br /&gt;
 |→&lt;br /&gt;
 |2&lt;br /&gt;
 |-&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |б&lt;br /&gt;
 |&lt;br /&gt;
 |р&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |к&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |д&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |б&lt;br /&gt;
 |&lt;br /&gt;
 |р&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
|}&lt;br /&gt;
====Сложность оптимизированного алгоритма====&lt;br /&gt;
Данный алгоритм работает за &amp;lt;tex&amp;gt;O(N\log{N})&amp;lt;/tex&amp;gt; времени и требует &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt; памяти. Однако, если размер алфавита не очень большой, то для выяснения первого столбца матрицы можно использовать сортировку подсчетом, в этом случае алгоритм работает за &amp;lt;tex&amp;gt;O(N+M)&amp;lt;/tex&amp;gt; действий и требует &amp;lt;tex&amp;gt;O(N+M)&amp;lt;/tex&amp;gt; памяти, где &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; — размер алфавита.&lt;br /&gt;
&lt;br /&gt;
====Псевдокод оптимизированного алгоритма====&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; N &amp;lt;/tex&amp;gt; — количество символов во входной строке, &amp;lt;tex&amp;gt; M &amp;lt;/tex&amp;gt; — количество символов в алфавите, &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; — номер исходной строки в матрице перестановок, &amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt; — входящая строка, &amp;lt;tex&amp;gt; count &amp;lt;/tex&amp;gt;  — массив для сортировки подсчетом, &amp;lt;tex&amp;gt; t &amp;lt;/tex&amp;gt; — вектор обратного преобразования, &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; — номер данной нам строки в таблице.&lt;br /&gt;
&lt;br /&gt;
  '''function''' reverseBWT(N : Int, M : Int, k : Int, s : String): Int[]&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Cчитаем частоты символов&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' i = 0 .. M &lt;br /&gt;
      count[i] = 0&lt;br /&gt;
    '''for''' i = 0 .. N &lt;br /&gt;
      count[s[i]]++&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Упорядочиваем символы, чтобы получить первый столбец исходной матрицы&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// count[i] указывает на первую позицию символа i в первом столбце&amp;lt;/font&amp;gt;&lt;br /&gt;
    sum = 0&lt;br /&gt;
    '''for''' i = 0 .. M&lt;br /&gt;
      sum = sum + count[i]&lt;br /&gt;
      count[i] = sum - count[i]&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Cоздаем вектор обратного преобразования&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' i = 0 .. N&lt;br /&gt;
    t[count[s[i]]] = i&lt;br /&gt;
    count[s[i]]++&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// И восстанавливаем исходный текст&amp;lt;/font&amp;gt;&lt;br /&gt;
    j = t[x]&lt;br /&gt;
    '''for''' i = 0 .. N&lt;br /&gt;
      answer[i] = s[j]&lt;br /&gt;
      j = t[j]&lt;br /&gt;
    return answer&lt;br /&gt;
&lt;br /&gt;
====Доказательство корректности====&lt;br /&gt;
&lt;br /&gt;
Пусть текст &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; состоит из &amp;lt;tex&amp;gt;N + 1&amp;lt;/tex&amp;gt; символов, занумерованных с нуля: &amp;lt;tex&amp;gt;T[0..N]&amp;lt;/tex&amp;gt;. Буквы &amp;lt;tex&amp;gt;T[i]&amp;lt;/tex&amp;gt; принадлежат некоторому алфавиту &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Лексикографический порядок (строгий) на строках из алфавита &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; будем обозначать &amp;lt;tex&amp;gt;\preceq (\prec)&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt;S_{k}T&amp;lt;/tex&amp;gt; циклический сдвиг текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; символов влево:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt; S_{k}T = T[(j + k) (\bmod\ N + 1)] &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Существует перестановка &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;\{0, ..., N\}&amp;lt;/tex&amp;gt;, которая удовлетворяет условию: &lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt; S_{p(i)}T \preceq S_{p(i + 1)}T,\ i = 0, ..., N - 1\ \ \textbf{(1)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Преобразование Барроуза-Уилера текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; есть текст &amp;lt;tex&amp;gt;B[0..N] = BW(T)&amp;lt;/tex&amp;gt;, буквы которого заданы соотношением:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt;B[i] = S_{p(i)}T[N]&amp;lt;/tex&amp;gt;, другими словами &amp;lt;tex&amp;gt;B[i] = S_{p(i) - 1}T[0] = T[(p(i) - 1) (\bmod\ N + 1)] \ \ \textbf{(2)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} перестановка чисел &amp;lt;tex&amp;gt;\{0, ..., N\}&amp;lt;/tex&amp;gt;, удовлетворяющая условию:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt;B_{\sigma(i)} \preceq B_{\sigma(i + 1)}&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N - 1\ \ \textbf{(3)}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
|}&lt;br /&gt;
и в случае равенства &amp;lt;tex&amp;gt;B_{\sigma(i)}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;B_{\sigma(i + 1)}&amp;lt;/tex&amp;gt; выполнено {{---}} &amp;lt;tex&amp;gt;\sigma(i) &amp;lt; \sigma(i + 1)&amp;lt;/tex&amp;gt;. Перестановка однозначно определяется текстом &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; и ее можно посчитать за &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt;, используя сортировку подсчетом. Рассмотрим перестановку &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; как отображение &amp;lt;tex&amp;gt;\sigma : \{0, ..., N\} \to \{0, ..., N\}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;\sigma^{k}&amp;lt;/tex&amp;gt; копмозиция &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; отображений &amp;lt;tex&amp;gt;\sigma^{k} = \sigma^{k - 1} \circ \sigma&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\sigma^{1} = \sigma, \sigma^{0} \equiv i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
&lt;br /&gt;
''При всех &amp;lt;tex&amp;gt;m = 1, ..., N + 1&amp;lt;/tex&amp;gt; верны утверждения,&lt;br /&gt;
:&amp;lt;tex&amp;gt;B_{\sigma(i)}...B_{\sigma^{m}(i)} \preceq B_{\sigma(i + 1)}...B_{\sigma^{m}(i + 1)}&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N - 1\ \ \textbf{(4)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;B_iB_{\sigma(i)}...B_{\sigma^{m - 1}(i)} = S_{p(i) - 1}T[0..m - 1]&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N\ \ \textbf{(5)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
|proof=&lt;br /&gt;
&lt;br /&gt;
Если лексикографически отсортировать буквы последнего столбца и поместить их в первый столбец, то получится таблица&lt;br /&gt;
&lt;br /&gt;
| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Таблица&lt;br /&gt;
|-&lt;br /&gt;
|a||b||c&lt;br /&gt;
|-&lt;br /&gt;
|a||b||c&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
&lt;br /&gt;
''Для восстановления исходного текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из преобразования &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; достаточно знать число &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;, отвечающее условию &amp;lt;tex&amp;gt;p(I) = 0&amp;lt;/tex&amp;gt;, другими словами &amp;lt;tex&amp;gt;S_{p(I)}T = T&amp;lt;/tex&amp;gt;.''&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Алгоритм за линейное время===&lt;br /&gt;
&lt;br /&gt;
Будем обозначать &amp;lt;tex&amp;gt;s^i&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ую циклическую перестановку &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;s^0 = s_0 s_1 \ldots s_{n-1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;$BWT(s)$\;= L&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;L = L_0L_1\ldots L_{n-1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; -- номер строки &amp;lt;tex&amp;gt;s^0&amp;lt;/tex&amp;gt; в таблице. Предподсчитаем следующие величины:&lt;br /&gt;
* Для каждого &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt; количество символов на подстроке &amp;lt;tex&amp;gt;l_0, \ldots , l_{i-1}&amp;lt;/tex&amp;gt;, равных &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
* Для каждого уникального &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt; количество символов в &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;, лексикографически меньших, чем &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пример для &amp;lt;tex&amp;gt;$BWT(s) =$&amp;lt;/tex&amp;gt; &amp;quot;BCABAAA&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
!colspan=&amp;quot;3&amp;quot; | Таблица первого предподсчёта&lt;br /&gt;
|-&lt;br /&gt;
! Позиция || Символ || Результат&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
! 0 || B || 0&lt;br /&gt;
|-&lt;br /&gt;
! 1 || C || 0&lt;br /&gt;
|-&lt;br /&gt;
! 2 || A || 0&lt;br /&gt;
|-&lt;br /&gt;
! 3 || B || 1&lt;br /&gt;
|-&lt;br /&gt;
! 4 || A || 1&lt;br /&gt;
|-&lt;br /&gt;
! 5 || A || 2&lt;br /&gt;
|-&lt;br /&gt;
! 6 || A || 3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; | Таблица второго предподсчёта&lt;br /&gt;
|-&lt;br /&gt;
! Символ || Количество  &amp;lt;br /&amp;gt; меньших&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
! A || 0&lt;br /&gt;
|-&lt;br /&gt;
! B || 4&lt;br /&gt;
|-&lt;br /&gt;
! C || 6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Для удобства пронумеруем известные нам данные:&lt;br /&gt;
# &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;, последний столбец таблицы перестановок&lt;br /&gt;
# &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;, номер строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt; в таблице перестановок&lt;br /&gt;
# Частота, с которой символ &amp;lt;tex&amp;gt;L_{i}&amp;lt;/tex&amp;gt; встречается в подстроке &amp;lt;tex&amp;gt;l_0, \ldots , l_{i-1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
# Для каждого уникального символа количество лексикографически меньших символов в &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Символ &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt; находится в строке &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; под номером &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;, так как в таблице строка &amp;lt;tex&amp;gt;s^0&amp;lt;/tex&amp;gt; имела номер &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;. Найдём символ &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Символ &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt; имеет в строке &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; тот же номер, что строка &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt; имела в таблице перестановок: строка &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt; начинается с символа &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt; находится на 1 левее его и из-за циклического сдвига оказывается в последнем столбце. Нам известен символ &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;. Посчитаем, на каком месте в таблице будет стоять строка, начинающаяся с этого символа.&lt;br /&gt;
&lt;br /&gt;
Из 4 известно количество символов, меньших &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;. Все строки, начинающиеся с этих символов, стоят в таблице раньше &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt;. Кроме того, в таблице есть строки, начинающиеся с того же символа, что и &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt;. Из 3 известно, сколько их: если символ, равный &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, встречался в &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; раньше, чем &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, то в таблице строка, начинающаяся с этого символа, тоже стоит раньше строки, начинающейся с &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, так как префикс строки, оканчивающейся на этот символ, меньше префикса строки, оканчивающейся на &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Тогда сумма этих двух величин является номером символа &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt; в строке &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;. Зная &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt;, аналогично найдём &amp;lt;tex&amp;gt;s_{n-3}\ldots s_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предподсчёт занимает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени, восстановление каждого из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; символов занимает &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; времени. Суммарное время работы алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пример работы для &amp;lt;tex&amp;gt;$BWT(s) = ($&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, 2&amp;lt;tex&amp;gt;)&amp;lt;/tex&amp;gt; (нумерация с 0):&lt;br /&gt;
* &amp;lt;tex&amp;gt;s^0 = .......&amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;s_6=L_2 = A&amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt;s^0=......&amp;lt;/tex&amp;gt;A&lt;br /&gt;
* Суммируем значения из двух таблиц: &amp;lt;tex&amp;gt;0+0=0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_5=L_0=B&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=.....&amp;lt;/tex&amp;gt;BA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;0+4=4&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_4=L_4=A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=....&amp;lt;/tex&amp;gt;ABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;1+0=1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_3=L_1=C&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=...&amp;lt;/tex&amp;gt;CABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;0+6=6&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_2=L_6=A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=..&amp;lt;/tex&amp;gt;ACABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;3+0=3&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_2=L_3=B&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=.&amp;lt;/tex&amp;gt;BACABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;1+4=5&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_2=L_5=A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=&amp;lt;/tex&amp;gt; ABACABA&lt;br /&gt;
&lt;br /&gt;
== Дополнительно ==&lt;br /&gt;
&lt;br /&gt;
* bzip2&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Bzip2 bzip2]&amp;lt;/ref&amp;gt; использует преобразование Барроуза {{---}} Уилера для превращения последовательностей многократно чередующихся символов в строки одинаковых символов, затем применяет преобразование [[Преобразование_MTF | MTF]], и в конце кодирование Хаффмана.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Алгоритм_Хаффмана | Алгоритм Хаффмана]]&lt;br /&gt;
* [[Алгоритмы_LZ77_и_LZ78 | Алгоритмы LZ77 и LZ78]]&lt;br /&gt;
* [[Арифметическое_кодирование | Арифметическое кодирование]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
*[http://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0_%E2%80%94_%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0 Википедия: Преобразование Барроуза {{---}} Уилера]&lt;br /&gt;
&lt;br /&gt;
*[http://www.cs.karelia.ru/~aborod/inf/2010/schedule.php.ru cs.karelia.ru: Преобразование Барроуза {{---}} Уилера]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы сжатия ]]&lt;/div&gt;</summary>
		<author><name>Evarand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0-%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0&amp;diff=50188</id>
		<title>Преобразование Барроуза-Уилера</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0-%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0&amp;diff=50188"/>
				<updated>2015-12-12T19:15:21Z</updated>
		
		<summary type="html">&lt;p&gt;Evarand: Косметические изменения&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
'''Преобразование Барроуза {{---}} Уилера''' (англ. ''Burrows-Wheeler transform'') {{---}} алгоритм, используемый для предварительной обработки данных перед сжатием, разработанный для улучшения эффективности последующего кодирования. Преобразование Барроуза {{---}} Уилера меняет порядок символов во входной строке таким образом, что повторяющиеся подстроки образуют на выходе идущие подряд последовательности одинаковых символов.&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Преобразование выполняется в три этапа:&lt;br /&gt;
# Составляется таблица всех циклических сдвигов входной строки.&lt;br /&gt;
# Производится лексикографическая (в алфавитном порядке) сортировка строк таблицы.&lt;br /&gt;
# В качестве выходной строки выбирается последний столбец таблицы преобразования и номер строки, совпадающей с исходной.&lt;br /&gt;
&lt;br /&gt;
== Пример работы алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дана исходная строка &amp;lt;tex&amp;gt;$s =$&amp;lt;/tex&amp;gt; &amp;quot;ABACABA&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;4&amp;quot;|Трансформация&lt;br /&gt;
|-&lt;br /&gt;
! Вход || Все&amp;lt;br /&amp;gt;циклические &amp;lt;br /&amp;gt; сдвиги || Сортировка&amp;lt;br /&amp;gt;строк || Выход&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
BACABAA&amp;lt;br/&amp;gt;&lt;br /&gt;
ACABAAB&amp;lt;br/&amp;gt;&lt;br /&gt;
CABAABA&amp;lt;br/&amp;gt;&lt;br /&gt;
ABAABAC&amp;lt;br/&amp;gt;&lt;br /&gt;
BAABACA&amp;lt;br/&amp;gt;&lt;br /&gt;
AABACAB&amp;lt;br/&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
AABACAB&amp;lt;br/&amp;gt;&lt;br /&gt;
ABAABAC&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
ACABAAB&amp;lt;br/&amp;gt;&lt;br /&gt;
BAABACA&amp;lt;br/&amp;gt;&lt;br /&gt;
BACABAA&amp;lt;br/&amp;gt;&lt;br /&gt;
CABAABA &amp;lt;br/&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
BCABAAA, 3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Результат можно записать так: &amp;lt;tex&amp;gt;$BWT(s) = $(&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, &amp;lt;tex&amp;gt;3)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; {{---}} номер исходной строки в отсортированной матрице. Он нужен для обратного преобразования. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следует заметить, что иногда в исходной строке приводится так называемый символ конца строки &amp;lt;tex&amp;gt;\$&amp;lt;/tex&amp;gt;, который в преобразовании будет считаться последним (максимальным) символом, тогда сохранение номера исходной строки не требуется.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пусть нам дана исходная строка &amp;lt;tex&amp;gt;$s =$&amp;lt;/tex&amp;gt; &amp;quot;ABACABA$&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;4&amp;quot;|Трансформация&lt;br /&gt;
|-&lt;br /&gt;
! Вход || Все&amp;lt;br /&amp;gt;Перестановки || Сортировка&amp;lt;br /&amp;gt;Строк || Выход&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
BACABA$A&amp;lt;br/&amp;gt;&lt;br /&gt;
ACABA$AB&amp;lt;br/&amp;gt;&lt;br /&gt;
CABA$ABA&amp;lt;br/&amp;gt;&lt;br /&gt;
ABA$ABAC&amp;lt;br/&amp;gt;&lt;br /&gt;
BA$ABACA&amp;lt;br/&amp;gt;&lt;br /&gt;
A$ABACAB&amp;lt;br/&amp;gt;&lt;br /&gt;
$ABACABA&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
ABA$ABAC&amp;lt;br/&amp;gt;&lt;br /&gt;
ACABA$AB&amp;lt;br/&amp;gt;&lt;br /&gt;
A$ABACAB&amp;lt;br/&amp;gt;&lt;br /&gt;
BACABA$A&amp;lt;br/&amp;gt;&lt;br /&gt;
BA$ABACA&amp;lt;br/&amp;gt;&lt;br /&gt;
CABA$ABA &amp;lt;br/&amp;gt;&lt;br /&gt;
$ABACABA&lt;br /&gt;
|&lt;br /&gt;
$CBBAAAA&lt;br /&gt;
|} &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
При аналогичном вышеприведённом преобразовании та строчка в матрице, которая будет заканчиваться на символ конца строки, и будет исходной: (&amp;quot;ABACABA$&amp;quot;). Тогда результат можно записать так: &amp;lt;tex&amp;gt;$BWT(s) =$&amp;lt;/tex&amp;gt; &amp;quot;$CBBAAAA&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Обратное преобразование ==&lt;br /&gt;
&lt;br /&gt;
===Наивный алгоритм===&lt;br /&gt;
&lt;br /&gt;
Пусть нам дано: &amp;lt;tex&amp;gt;$BWT(s) =$(&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, &amp;lt;tex&amp;gt;3)&amp;lt;/tex&amp;gt;. Тогда выпишем в столбик нашу преобразованную последовательность символов &amp;quot;BCABAAA&amp;quot;. Запишем её как последний столбик предыдущей матрицы (при прямом преобразовании Барроуза {{---}} Уилера), при этом все предыдущие столбцы оставляем пустыми. Далее построчно [[Сортировки | отсортируем]] матрицу, затем в предыдущий столбец запишем &amp;quot;BCABAAA&amp;quot;. Опять построчно отсортируем матрицу. Продолжая таким образом, можно восстановить полный список всех циклических перестановок строки, которую нам надо найти. Выстроив полный отсортированный список перестановок, выберем строку с номером, который нам был изначально дан. В итоге мы получим искомую строку.&lt;br /&gt;
Алгоритм обратного преобразования описан в таблице ниже:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Обратное преобразование&lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Вход&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot; colspan=&amp;quot;8&amp;quot;|&lt;br /&gt;
BCABAAA&lt;br /&gt;
|-&lt;br /&gt;
! Добавление 1 || Сортировка 1 || Добавление 2 || Сортировка 2 || Добавление 3 || Сортировка 3 || Добавление 4 &lt;br /&gt;
|-align=&amp;quot;right&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
 B&lt;br /&gt;
 C&lt;br /&gt;
 A&lt;br /&gt;
 B&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
|&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 B&lt;br /&gt;
 B&lt;br /&gt;
 C&lt;br /&gt;
|&lt;br /&gt;
 BA&lt;br /&gt;
 CA&lt;br /&gt;
 AA&lt;br /&gt;
 BA&lt;br /&gt;
 AB&lt;br /&gt;
 AB&lt;br /&gt;
 AC&lt;br /&gt;
|&lt;br /&gt;
 AA&lt;br /&gt;
 AB&lt;br /&gt;
 AB&lt;br /&gt;
 AC&lt;br /&gt;
 BA&lt;br /&gt;
 BA&lt;br /&gt;
 CA&lt;br /&gt;
|&lt;br /&gt;
 BAA&lt;br /&gt;
 CAB&lt;br /&gt;
 AAB&lt;br /&gt;
 BAC&lt;br /&gt;
 ABA&lt;br /&gt;
 ABA&lt;br /&gt;
 ACA&lt;br /&gt;
|&lt;br /&gt;
 AAB&lt;br /&gt;
 ABA&lt;br /&gt;
 ABA&lt;br /&gt;
 ACA&lt;br /&gt;
 BAA&lt;br /&gt;
 BAC&lt;br /&gt;
 CAB&lt;br /&gt;
|&lt;br /&gt;
 BAAB&lt;br /&gt;
 CABA&lt;br /&gt;
 AABA&lt;br /&gt;
 BACA&lt;br /&gt;
 ABAA&lt;br /&gt;
 ABAC&lt;br /&gt;
 ACAB&lt;br /&gt;
|-&lt;br /&gt;
! Сортировка 4 || Добавление 5 || Сортировка 5 || Добавление 6 || Сортировка 6 || Добавление 7 || Сортировка 7&lt;br /&gt;
&lt;br /&gt;
|-align=&amp;quot;right&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
 AABA&lt;br /&gt;
 ABAA&lt;br /&gt;
 ABAC&lt;br /&gt;
 ACAB&lt;br /&gt;
 BAAB&lt;br /&gt;
 BACA&lt;br /&gt;
 CABA&lt;br /&gt;
|&lt;br /&gt;
 BAABA&lt;br /&gt;
 CABAA&lt;br /&gt;
 AABAC&lt;br /&gt;
 BACAB&lt;br /&gt;
 ABAAB&lt;br /&gt;
 ABACA&lt;br /&gt;
 ACABA&lt;br /&gt;
|&lt;br /&gt;
 AABAC&lt;br /&gt;
 ABAAB&lt;br /&gt;
 ABACA&lt;br /&gt;
 ACABA&lt;br /&gt;
 BAABA&lt;br /&gt;
 BACAB&lt;br /&gt;
 CABAA&lt;br /&gt;
|&lt;br /&gt;
 BAABAC&lt;br /&gt;
 CABAAB&lt;br /&gt;
 AABACA&lt;br /&gt;
 BACABA&lt;br /&gt;
 ABAABA&lt;br /&gt;
 ABACAB&lt;br /&gt;
 ACABAA&lt;br /&gt;
|&lt;br /&gt;
 AABACA&lt;br /&gt;
 ABAABA&lt;br /&gt;
 ABACAB&lt;br /&gt;
 ACABAA&lt;br /&gt;
 BAABAC&lt;br /&gt;
 BACABA&lt;br /&gt;
 CABAAB&lt;br /&gt;
|&lt;br /&gt;
 BAABACA&lt;br /&gt;
 CABAABA&lt;br /&gt;
 AABACAB&lt;br /&gt;
 BACABAA&lt;br /&gt;
 ABAABAC&lt;br /&gt;
 ABACABA&lt;br /&gt;
 ACABAAB&lt;br /&gt;
|&lt;br /&gt;
 AABACAB&lt;br /&gt;
 ABAABAC&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
 ACABAAB&lt;br /&gt;
 BAABACA&lt;br /&gt;
 BACABAA&lt;br /&gt;
 CABAABA&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Результат&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot; colspan=&amp;quot;8&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Следует также заметить, что если нам было бы дано &amp;lt;tex&amp;gt;$BWT(s) = $&amp;lt;/tex&amp;gt; &amp;quot;$CBBAAAA&amp;quot;, то мы также получили бы нашу исходную строку, только с символом конца строки &amp;lt;tex&amp;gt;\$&amp;lt;/tex&amp;gt; на конце: ABACABA$.&lt;br /&gt;
&lt;br /&gt;
Временная сложность данного алгоритма &amp;lt;tex&amp;gt;O(N^3\log{N}) &amp;lt;/tex&amp;gt;, пространственная &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Доказательство корректности====&lt;br /&gt;
&lt;br /&gt;
Пусть дана строка &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;, к которой было применено преобразование BWT. Докажем, что при использовании наивного алгоритма на каждом шаге получающийся набор строк соответствует суффиксам циклических перестановок исходной строки, методом математической индукции.&lt;br /&gt;
* '''База'''. Циклически сдвинем все строки исходной таблицы на &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; влево. Тогда в столбце &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; будут находиться символы, добавленные на первом шаге алгоритма, а в столбце &amp;lt;tex&amp;gt;n - 1&amp;lt;/tex&amp;gt; символы, изначально стоявшие в таблице до первого шага алгоритма. Таким образом, полученные на первом шаге алгоритма строки являются суффиксами циклических перестановок строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* '''Предположение'''. Пусть на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; шаге алгоритма все полученные строки являются суффиксами циклических перестановок строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* '''Переход'''. Рассмотрим &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ый шаг алгоритма. Все строки отсортированы, поэтому самый левый столбец совпадет с &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; столбцом исходной таблицы. Циклически сдвинем все строки исходной таблицы на &amp;lt;tex&amp;gt;n - k&amp;lt;/tex&amp;gt; символов вправо. Теперь по предположению первые &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; символов справа в каждой строке совпадают у исходной таблицы и у таблицы, полученной в результате работы алгоритма. &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;-ые справа столбцы также совпадают. Добавленный на &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ом шаге столбец также совпадает с &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ым справа столбцом сдвинутой исходной таблицы, так как совпадает с последним столбцом исходной таблицы, которая была сдвинута на &amp;lt;tex&amp;gt;n-k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;3&amp;quot; | &amp;lt;tex&amp;gt;$k+1$&amp;lt;/tex&amp;gt; шаг алгоритма при &amp;lt;tex&amp;gt;$k=3$&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! Исходная &amp;lt;br /&amp;gt; таблица || Сдвинутая &amp;lt;br /&amp;gt; таблица || Результат &amp;lt;br /&amp;gt; работы &amp;lt;br /&amp;gt; алгоритма&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;CA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt;BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt;AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt;AA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt;AC&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt;BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
CA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
AA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
AC&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:right;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Таким образом, поскольку на каждом шаге алгоритма получившиеся строки являлись суффиксами циклических перестановок &amp;lt;tex&amp;gt; $s$ &amp;lt;/tex&amp;gt;, после последнего шага получившиеся строки будут совпадать с циклическими перестановками &amp;lt;tex&amp;gt; $s$ &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Оптимизированный наивный алгоритм===&lt;br /&gt;
&lt;br /&gt;
Наивный алгоритм можно оптимизировать. Заметим, что при каждом проявлении неизвестного столбца выполнялись одни и те же действия. Мы приписывали новый столбец и сортировали имеющиеся данные. На каждом шагу мы к строке, которая находилась на &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;-ом месте приписываем в начало &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; -ый элемент столбца входных данных. Пусть изначально мы знаем каким по порядку является приписанный нами в начало символ (то есть каким по порядку в столбце). И конечно же мы знаем исходя из предыдущего шага какое место занимала наша строка без этого первого символа (&amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; -ое). Тогда несложно заметить, что при выполнении такой операции строка с номером &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; всегда будет перемещаться на позицию с номером &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |0||а||&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;||р||9&lt;br /&gt;
  |-&lt;br /&gt;
  |1||а||||д||7&lt;br /&gt;
  |-&lt;br /&gt;
  |2||а|| ||a||0&lt;br /&gt;
  |-&lt;br /&gt;
  |3||а|| ||к||8&lt;br /&gt;
  |-&lt;br /&gt;
  |4||а|| ||р||10&lt;br /&gt;
  |-&lt;br /&gt;
  |5||б|| ||a||1&lt;br /&gt;
  |-&lt;br /&gt;
  |6||б|| ||a||2&lt;br /&gt;
  |-&lt;br /&gt;
  |7||д|| ||a||3&lt;br /&gt;
  |-&lt;br /&gt;
  |8||к|| ||a||4&lt;br /&gt;
  |-&lt;br /&gt;
  |9||р|| ||б||5&lt;br /&gt;
  |-&lt;br /&gt;
  |10||р|| ||б||6&lt;br /&gt;
  |}&lt;br /&gt;
&lt;br /&gt;
Здесь слева отсортированный данный столбец, чтобы мы знали, какое место в лексикографическом порядке занимает приписываемый нами символ среди всех элементов данного нам изначально столбца. Справа - изначально данный столбец и соответствующее ему число. Поскольку в нашем алгоритме новый столбец приписывается в начало, то мы из состояния &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; (левый столбец) переходим в состояние &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; (правый). Для того, чтобы восстановить строку, нам необходимо от последней такой цифры по пути из &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; восстановить строку.&lt;br /&gt;
{|&lt;br /&gt;
 |&lt;br /&gt;
 {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
 |6&lt;br /&gt;
 |→&lt;br /&gt;
 |10&lt;br /&gt;
 |→&lt;br /&gt;
 |4 &lt;br /&gt;
 |→&lt;br /&gt;
 |8&lt;br /&gt;
 |→ &lt;br /&gt;
 |3&lt;br /&gt;
 |→&lt;br /&gt;
 |7&lt;br /&gt;
 |→&lt;br /&gt;
 |1&lt;br /&gt;
 |→&lt;br /&gt;
 |5&lt;br /&gt;
 |→&lt;br /&gt;
 |9&lt;br /&gt;
 |→&lt;br /&gt;
 |0&lt;br /&gt;
 |→&lt;br /&gt;
 |2&lt;br /&gt;
 |-&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |б&lt;br /&gt;
 |&lt;br /&gt;
 |р&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |к&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |д&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |б&lt;br /&gt;
 |&lt;br /&gt;
 |р&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
|}&lt;br /&gt;
====Сложность оптимизированного алгоритма====&lt;br /&gt;
Данный алгоритм работает за &amp;lt;tex&amp;gt;O(N\log{N})&amp;lt;/tex&amp;gt; времени и требует &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt; памяти. Однако, если размер алфавита не очень большой, то для выяснения первого столбца матрицы можно использовать сортировку подсчетом, в этом случае алгоритм работает за &amp;lt;tex&amp;gt;O(N+M)&amp;lt;/tex&amp;gt; действий и требует &amp;lt;tex&amp;gt;O(N+M)&amp;lt;/tex&amp;gt; памяти, где &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; — размер алфавита.&lt;br /&gt;
&lt;br /&gt;
====Псевдокод оптимизированного алгоритма====&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; N &amp;lt;/tex&amp;gt; — количество символов во входной строке, &amp;lt;tex&amp;gt; M &amp;lt;/tex&amp;gt; — количество символов в алфавите, &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; — номер исходной строки в матрице перестановок, &amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt; — входящая строка, &amp;lt;tex&amp;gt; count &amp;lt;/tex&amp;gt;  — массив для сортировки подсчетом, &amp;lt;tex&amp;gt; t &amp;lt;/tex&amp;gt; — вектор обратного преобразования, &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; — номер данной нам строки в таблице.&lt;br /&gt;
&lt;br /&gt;
  function reverseBWT(N : Int, M : Int, k : Int, s : Stirng): Int[]&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Cчитаем частоты символов&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' i = 0 .. M &lt;br /&gt;
      count[i] = 0&lt;br /&gt;
    '''for''' i = 0 .. N &lt;br /&gt;
      count[s[i]]++&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Упорядочиваем символы, чтобы получить первый столбец исходной матрицы&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// count[i] указывает на первую позицию символа i в первом столбце&amp;lt;/font&amp;gt;&lt;br /&gt;
    sum = 0&lt;br /&gt;
    '''for''' i = 0 .. M&lt;br /&gt;
      sum = sum + count[i]&lt;br /&gt;
      count[i] = sum - count[i]&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Cоздаем вектор обратного преобразования&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' i = 0 .. N&lt;br /&gt;
    t[count[s[i]]] = i&lt;br /&gt;
    count[s[i]]++&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// И восстанавливаем исходный текст&amp;lt;/font&amp;gt;&lt;br /&gt;
    j = t[x]&lt;br /&gt;
    '''for''' i = 0 .. N&lt;br /&gt;
      answer[i] = s[j]&lt;br /&gt;
      j = t[j]&lt;br /&gt;
    return answer&lt;br /&gt;
&lt;br /&gt;
====Доказательство корректности====&lt;br /&gt;
&lt;br /&gt;
Пусть текст &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; состоит из &amp;lt;tex&amp;gt;N + 1&amp;lt;/tex&amp;gt; символов, занумерованных с нуля: &amp;lt;tex&amp;gt;T[0..N]&amp;lt;/tex&amp;gt;. Буквы &amp;lt;tex&amp;gt;T[i]&amp;lt;/tex&amp;gt; принадлежат некоторому алфавиту &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Лексикографический порядок (строгий) на строках из алфавита &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; будем обозначать &amp;lt;tex&amp;gt;\preceq (\prec)&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt;S_{k}T&amp;lt;/tex&amp;gt; циклический сдвиг текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; символов влево:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt; S_{k}T = T[(j + k) (\bmod\ N + 1)] &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Существует перестановка &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;\{0, ..., N\}&amp;lt;/tex&amp;gt;, которая удовлетворяет условию: &lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt; S_{p(i)}T \preceq S_{p(i + 1)}T,\ i = 0, ..., N - 1\ \ \textbf{(1)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Преобразование Барроуза-Уилера текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; есть текст &amp;lt;tex&amp;gt;B[0..N] = BW(T)&amp;lt;/tex&amp;gt;, буквы которого заданы соотношением:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt;B[i] = S_{p(i)}T[N]&amp;lt;/tex&amp;gt;, другими словами &amp;lt;tex&amp;gt;B[i] = S_{p(i) - 1}T[0] = T[(p(i) - 1) (\bmod\ N + 1)] \ \ \textbf{(2)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} перестановка чисел &amp;lt;tex&amp;gt;\{0, ..., N\}&amp;lt;/tex&amp;gt;, удовлетворяющая условию:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt;B_{\sigma(i)} \preceq B_{\sigma(i + 1)}&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N - 1\ \ \textbf{(3)}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
|}&lt;br /&gt;
и в случае равенства &amp;lt;tex&amp;gt;B_{\sigma(i)}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;B_{\sigma(i + 1)}&amp;lt;/tex&amp;gt; выполнено {{---}} &amp;lt;tex&amp;gt;\sigma(i) &amp;lt; \sigma(i + 1)&amp;lt;/tex&amp;gt;. Перестановка однозначно определяется текстом &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; и ее можно посчитать за &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt;, используя сортировку подсчетом. Рассмотрим перестановку &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; как отображение &amp;lt;tex&amp;gt;\sigma : \{0, ..., N\} \to \{0, ..., N\}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;\sigma^{k}&amp;lt;/tex&amp;gt; копмозиция &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; отображений &amp;lt;tex&amp;gt;\sigma^{k} = \sigma^{k - 1} \circ \sigma&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\sigma^{1} = \sigma, \sigma^{0} \equiv i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
&lt;br /&gt;
''При всех &amp;lt;tex&amp;gt;m = 1, ..., N + 1&amp;lt;/tex&amp;gt; верны утверждения,&lt;br /&gt;
:&amp;lt;tex&amp;gt;B_{\sigma(i)}...B_{\sigma^{m}(i)} \preceq B_{\sigma(i + 1)}...B_{\sigma^{m}(i + 1)}&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N - 1\ \ \textbf{(4)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;B_iB_{\sigma(i)}...B_{\sigma^{m - 1}(i)} = S_{p(i) - 1}T[0..m - 1]&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N\ \ \textbf{(5)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
|proof=&lt;br /&gt;
&lt;br /&gt;
Если лексикографически отсортировать буквы последнего столбца и поместить их в первый столбец, то получится таблица&lt;br /&gt;
&lt;br /&gt;
| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Таблица&lt;br /&gt;
|-&lt;br /&gt;
|a||b||c&lt;br /&gt;
|-&lt;br /&gt;
|a||b||c&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
&lt;br /&gt;
''Для восстановления исходного текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из преобразования &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; достаточно знать число &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;, отвечающее условию &amp;lt;tex&amp;gt;p(I) = 0&amp;lt;/tex&amp;gt;, другими словами &amp;lt;tex&amp;gt;S_{p(I)}T = T&amp;lt;/tex&amp;gt;.''&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Алгоритм за линейное время===&lt;br /&gt;
&lt;br /&gt;
Будем обозначать &amp;lt;tex&amp;gt;s^i&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ую циклическую перестановку &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;s^0 = s_0 s_1 \ldots s_{n-1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;$BWT(s)$\;= L&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;L = L_0L_1\ldots L_{n-1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; -- номер строки &amp;lt;tex&amp;gt;s^0&amp;lt;/tex&amp;gt; в таблице. Предподсчитаем следующие величины:&lt;br /&gt;
* Для каждого &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt; количество символов на подстроке &amp;lt;tex&amp;gt;l_0, \ldots , l_{i-1}&amp;lt;/tex&amp;gt;, равных &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
* Для каждого уникального &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt; количество символов в &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;, лексикографически меньших, чем &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пример для &amp;lt;tex&amp;gt;$BWT(s) =$&amp;lt;/tex&amp;gt; &amp;quot;BCABAAA&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
!colspan=&amp;quot;3&amp;quot; | Таблица первого предподсчёта&lt;br /&gt;
|-&lt;br /&gt;
! Позиция || Символ || Результат&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
! 0 || B || 0&lt;br /&gt;
|-&lt;br /&gt;
! 1 || C || 0&lt;br /&gt;
|-&lt;br /&gt;
! 2 || A || 0&lt;br /&gt;
|-&lt;br /&gt;
! 3 || B || 1&lt;br /&gt;
|-&lt;br /&gt;
! 4 || A || 1&lt;br /&gt;
|-&lt;br /&gt;
! 5 || A || 2&lt;br /&gt;
|-&lt;br /&gt;
! 6 || A || 3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; | Таблица второго предподсчёта&lt;br /&gt;
|-&lt;br /&gt;
! Символ || Количество  &amp;lt;br /&amp;gt; меньших&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
! A || 0&lt;br /&gt;
|-&lt;br /&gt;
! B || 4&lt;br /&gt;
|-&lt;br /&gt;
! C || 6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Для удобства пронумеруем известные нам данные:&lt;br /&gt;
# &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;, последний столбец таблицы перестановок&lt;br /&gt;
# &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;, номер строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt; в таблице перестановок&lt;br /&gt;
# Частота, с которой символ &amp;lt;tex&amp;gt;L_{i}&amp;lt;/tex&amp;gt; встречается в подстроке &amp;lt;tex&amp;gt;l_0, \ldots , l_{i-1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
# Для каждого уникального символа количество лексикографически меньших символов в &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Символ &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt; находится в строке &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; под номером &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;, так как в таблице строка &amp;lt;tex&amp;gt;s^0&amp;lt;/tex&amp;gt; имела номер &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;. Найдём символ &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Символ &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt; имеет в строке &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; тот же номер, что строка &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt; имела в таблице перестановок: строка &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt; начинается с символа &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt; находится на 1 левее его и из-за циклического сдвига оказывается в последнем столбце. Нам известен символ &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;. Посчитаем, на каком месте в таблице будет стоять строка, начинающаяся с этого символа.&lt;br /&gt;
&lt;br /&gt;
Из 4 известно количество символов, меньших &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;. Все строки, начинающиеся с этих символов, стоят в таблице раньше &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt;. Кроме того, в таблице есть строки, начинающиеся с того же символа, что и &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt;. Из 3 известно, сколько их: если символ, равный &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, встречался в &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; раньше, чем &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, то в таблице строка, начинающаяся с этого символа, тоже стоит раньше строки, начинающейся с &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, так как префикс строки, оканчивающейся на этот символ, меньше префикса строки, оканчивающейся на &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Тогда сумма этих двух величин является номером символа &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt; в строке &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;. Зная &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt;, аналогично найдём &amp;lt;tex&amp;gt;s_{n-3}\ldots s_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предподсчёт занимает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени, восстановление каждого из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; символов занимает &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; времени. Суммарное время работы алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пример работы для &amp;lt;tex&amp;gt;$BWT(s) = ($&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, 2&amp;lt;tex&amp;gt;)&amp;lt;/tex&amp;gt; (нумерация с 0):&lt;br /&gt;
* &amp;lt;tex&amp;gt;s^0 = .......&amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;s_6=L_2 = A&amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt;s^0=......&amp;lt;/tex&amp;gt;A&lt;br /&gt;
* Суммируем значения из двух таблиц: &amp;lt;tex&amp;gt;0+0=0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_5=L_0=B&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=.....&amp;lt;/tex&amp;gt;BA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;0+4=4&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_4=L_4=A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=....&amp;lt;/tex&amp;gt;ABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;1+0=1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_3=L_1=C&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=...&amp;lt;/tex&amp;gt;CABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;0+6=6&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_2=L_6=A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=..&amp;lt;/tex&amp;gt;ACABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;3+0=3&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_2=L_3=B&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=.&amp;lt;/tex&amp;gt;BACABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;1+4=5&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_2=L_5=A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=&amp;lt;/tex&amp;gt; ABACABA&lt;br /&gt;
&lt;br /&gt;
== Дополнительно ==&lt;br /&gt;
&lt;br /&gt;
* bzip2&amp;lt;ref&amp;gt;[https://ru.wikipedia.org/wiki/Bzip2 bzip2]&amp;lt;/ref&amp;gt; использует преобразование Барроуза {{---}} Уилера для превращения последовательностей многократно чередующихся символов в строки одинаковых символов, затем применяет преобразование [[Преобразование_MTF | MTF]], и в конце кодирование Хаффмана.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Алгоритм_Хаффмана | Алгоритм Хаффмана]]&lt;br /&gt;
* [[Алгоритмы_LZ77_и_LZ78 | Алгоритмы LZ77 и LZ78]]&lt;br /&gt;
* [[Арифметическое_кодирование | Арифметическое кодирование]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
*[http://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0_%E2%80%94_%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0 Википедия: Преобразование Барроуза {{---}} Уилера]&lt;br /&gt;
&lt;br /&gt;
*[http://www.cs.karelia.ru/~aborod/inf/2010/schedule.php.ru cs.karelia.ru: Преобразование Барроуза {{---}} Уилера]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы сжатия ]]&lt;/div&gt;</summary>
		<author><name>Evarand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0-%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0&amp;diff=50159</id>
		<title>Преобразование Барроуза-Уилера</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0-%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0&amp;diff=50159"/>
				<updated>2015-12-06T19:37:19Z</updated>
		
		<summary type="html">&lt;p&gt;Evarand: Таблицы&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Определение ==&lt;br /&gt;
&lt;br /&gt;
'''Преобразование Барроуза {{---}} Уилера''' (англ. ''Burrows-Wheeler transform'') {{---}} алгоритм, используемый для предварительной обработки данных перед сжатием, разработанный для улучшения эффективности последующего кодирования. Преобразование Барроуза {{---}} Уилера меняет порядок символов во входной строке таким образом, что повторяющиеся подстроки образуют на выходе идущие подряд последовательности одинаковых символов.&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Преобразование выполняется в три этапа. &lt;br /&gt;
* Составляется таблица всех циклических сдвигов входной строки.&lt;br /&gt;
* Производится лексикографическая (в алфавитном порядке) сортировка строк таблицы.&lt;br /&gt;
* В качестве выходной строки выбирается последний столбец таблицы преобразования и номер строки, совпадающей с исходной.&lt;br /&gt;
&lt;br /&gt;
== Пример работы алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дана исходная строка &amp;lt;tex&amp;gt;$s =$&amp;lt;/tex&amp;gt; &amp;quot;ABACABA&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;4&amp;quot;|Трансформация&lt;br /&gt;
|-&lt;br /&gt;
! Вход || Все&amp;lt;br /&amp;gt;перестановки || Сортировка&amp;lt;br /&amp;gt;строк || Выход&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
BACABAA&amp;lt;br/&amp;gt;&lt;br /&gt;
ACABAAB&amp;lt;br/&amp;gt;&lt;br /&gt;
CABAABA&amp;lt;br/&amp;gt;&lt;br /&gt;
ABAABAC&amp;lt;br/&amp;gt;&lt;br /&gt;
BAABACA&amp;lt;br/&amp;gt;&lt;br /&gt;
AABACAB&amp;lt;br/&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
AABACAB&amp;lt;br/&amp;gt;&lt;br /&gt;
ABAABAC&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
ACABAAB&amp;lt;br/&amp;gt;&lt;br /&gt;
BAABACA&amp;lt;br/&amp;gt;&lt;br /&gt;
BACABAA&amp;lt;br/&amp;gt;&lt;br /&gt;
CABAABA &amp;lt;br/&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
BCABAAA, 3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Результат можно записать так: &amp;lt;tex&amp;gt;$BWT(s) = $(&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, &amp;lt;tex&amp;gt;3)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; {{---}} номер исходной строки в отсортированной матрице. Он нужен для обратного преобразования. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следует заметить, что иногда в исходной строке приводится так называемый символ конца строки &amp;lt;tex&amp;gt;\$&amp;lt;/tex&amp;gt;, который в преобразовании будет считаться последним (максимальным) символом, тогда сохранение номера исходной строки не требуется.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пусть нам дана исходная строка &amp;lt;tex&amp;gt;$s =$&amp;lt;/tex&amp;gt; &amp;quot;ABACABA$&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;4&amp;quot;|Трансформация&lt;br /&gt;
|-&lt;br /&gt;
! Вход || Все&amp;lt;br /&amp;gt;Перестановки || Сортировка&amp;lt;br /&amp;gt;Строк || Выход&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
BACABA$A&amp;lt;br/&amp;gt;&lt;br /&gt;
ACABA$AB&amp;lt;br/&amp;gt;&lt;br /&gt;
CABA$ABA&amp;lt;br/&amp;gt;&lt;br /&gt;
ABA$ABAC&amp;lt;br/&amp;gt;&lt;br /&gt;
BA$ABACA&amp;lt;br/&amp;gt;&lt;br /&gt;
A$ABACAB&amp;lt;br/&amp;gt;&lt;br /&gt;
$ABACABA&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
ABA$ABAC&amp;lt;br/&amp;gt;&lt;br /&gt;
ACABA$AB&amp;lt;br/&amp;gt;&lt;br /&gt;
A$ABACAB&amp;lt;br/&amp;gt;&lt;br /&gt;
BACABA$A&amp;lt;br/&amp;gt;&lt;br /&gt;
BA$ABACA&amp;lt;br/&amp;gt;&lt;br /&gt;
CABA$ABA &amp;lt;br/&amp;gt;&lt;br /&gt;
$ABACABA&lt;br /&gt;
|&lt;br /&gt;
$CBBAAAA&lt;br /&gt;
|} &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
При аналогичном вышеприведённом преобразовании та строчка в матрице, которая будет заканчиваться на символ конца строки, и будет исходной: (&amp;quot;ABACABA$&amp;quot;). Тогда результат можно записать так: &amp;lt;tex&amp;gt;$BWT(s) =$&amp;lt;/tex&amp;gt; &amp;quot;$CBBAAAA&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Обратное преобразование ==&lt;br /&gt;
&lt;br /&gt;
===Наивный алгоритм===&lt;br /&gt;
&lt;br /&gt;
Пусть нам дано: &amp;lt;tex&amp;gt;$BWT(s) =$(&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, &amp;lt;tex&amp;gt;3)&amp;lt;/tex&amp;gt;. Тогда выпишем в столбик нашу преобразованную последовательность символов &amp;quot;BCABAAA&amp;quot;. Запишем её как последний столбик предыдущей матрицы (при прямом преобразовании Барроуза {{---}} Уилера), при этом все предыдущие столбцы оставляем пустыми. Далее построчно отсортируем матрицу, затем в предыдущий столбец запишем &amp;quot;BCABAAA&amp;quot;. Опять построчно отсортируем матрицу. Продолжая таким образом, можно восстановить полный список всех циклических перестановок строки, которую нам надо найти. Выстроив полный отсортированный список перестановок, выберем строку с номером, который нам был изначально дан. В итоге мы получим искомую строку.&lt;br /&gt;
Алгоритм обратного преобразования описан в таблице ниже:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Обратное преобразование&lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Вход&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot; colspan=&amp;quot;8&amp;quot;|&lt;br /&gt;
BCABAAA&lt;br /&gt;
|-&lt;br /&gt;
! Добавление 1 || Сортировка 1 || Добавление 2 || Сортировка 2 || Добавление 3 || Сортировка 3 || Добавление 4 &lt;br /&gt;
|-align=&amp;quot;right&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
 B&lt;br /&gt;
 C&lt;br /&gt;
 A&lt;br /&gt;
 B&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
|&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 B&lt;br /&gt;
 B&lt;br /&gt;
 C&lt;br /&gt;
|&lt;br /&gt;
 BA&lt;br /&gt;
 CA&lt;br /&gt;
 AA&lt;br /&gt;
 BA&lt;br /&gt;
 AB&lt;br /&gt;
 AB&lt;br /&gt;
 AC&lt;br /&gt;
|&lt;br /&gt;
 AA&lt;br /&gt;
 AB&lt;br /&gt;
 AB&lt;br /&gt;
 AC&lt;br /&gt;
 BA&lt;br /&gt;
 BA&lt;br /&gt;
 CA&lt;br /&gt;
|&lt;br /&gt;
 BAA&lt;br /&gt;
 CAB&lt;br /&gt;
 AAB&lt;br /&gt;
 BAC&lt;br /&gt;
 ABA&lt;br /&gt;
 ABA&lt;br /&gt;
 ACA&lt;br /&gt;
|&lt;br /&gt;
 AAB&lt;br /&gt;
 ABA&lt;br /&gt;
 ABA&lt;br /&gt;
 ACA&lt;br /&gt;
 BAA&lt;br /&gt;
 BAC&lt;br /&gt;
 CAB&lt;br /&gt;
|&lt;br /&gt;
 BAAB&lt;br /&gt;
 CABA&lt;br /&gt;
 AABA&lt;br /&gt;
 BACA&lt;br /&gt;
 ABAA&lt;br /&gt;
 ABAC&lt;br /&gt;
 ACAB&lt;br /&gt;
|-&lt;br /&gt;
! Сортировка 4 || Добавление 5 || Сортировка 5 || Добавление 6 || Сортировка 6 || Добавление 7 || Сортировка 7&lt;br /&gt;
&lt;br /&gt;
|-align=&amp;quot;right&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
 AABA&lt;br /&gt;
 ABAA&lt;br /&gt;
 ABAC&lt;br /&gt;
 ACAB&lt;br /&gt;
 BAAB&lt;br /&gt;
 BACA&lt;br /&gt;
 CABA&lt;br /&gt;
|&lt;br /&gt;
 BAABA&lt;br /&gt;
 CABAA&lt;br /&gt;
 AABAC&lt;br /&gt;
 BACAB&lt;br /&gt;
 ABAAB&lt;br /&gt;
 ABACA&lt;br /&gt;
 ACABA&lt;br /&gt;
|&lt;br /&gt;
 AABAC&lt;br /&gt;
 ABAAB&lt;br /&gt;
 ABACA&lt;br /&gt;
 ACABA&lt;br /&gt;
 BAABA&lt;br /&gt;
 BACAB&lt;br /&gt;
 CABAA&lt;br /&gt;
|&lt;br /&gt;
 BAABAC&lt;br /&gt;
 CABAAB&lt;br /&gt;
 AABACA&lt;br /&gt;
 BACABA&lt;br /&gt;
 ABAABA&lt;br /&gt;
 ABACAB&lt;br /&gt;
 ACABAA&lt;br /&gt;
|&lt;br /&gt;
 AABACA&lt;br /&gt;
 ABAABA&lt;br /&gt;
 ABACAB&lt;br /&gt;
 ACABAA&lt;br /&gt;
 BAABAC&lt;br /&gt;
 BACABA&lt;br /&gt;
 CABAAB&lt;br /&gt;
|&lt;br /&gt;
 BAABACA&lt;br /&gt;
 CABAABA&lt;br /&gt;
 AABACAB&lt;br /&gt;
 BACABAA&lt;br /&gt;
 ABAABAC&lt;br /&gt;
 ABACABA&lt;br /&gt;
 ACABAAB&lt;br /&gt;
|&lt;br /&gt;
 AABACAB&lt;br /&gt;
 ABAABAC&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
 ACABAAB&lt;br /&gt;
 BAABACA&lt;br /&gt;
 BACABAA&lt;br /&gt;
 CABAABA&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Результат&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot; colspan=&amp;quot;8&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Следует также заметить, что если нам было бы дано &amp;lt;tex&amp;gt;$BWT(s) = $&amp;lt;/tex&amp;gt; &amp;quot;$CBBAAAA&amp;quot;, то мы также получили бы нашу исходную строку, только с символом конца строки &amp;lt;tex&amp;gt;\$&amp;lt;/tex&amp;gt; на конце: ABACABA$.&lt;br /&gt;
&lt;br /&gt;
Временная сложность данного алгоритма &amp;lt;tex&amp;gt;O(N^3\log{N}) &amp;lt;/tex&amp;gt;, пространственная &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Доказательство корректности====&lt;br /&gt;
&lt;br /&gt;
Пусть дана строка &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;, к которой было применено преобразование BWT. Докажем, что при использовании наивного алгоритма на каждом шаге получающийся набор строк соответствует суффиксам циклических перестановок исходной строки, методом математической индукции.&lt;br /&gt;
* База. Циклически сдвинем все строки исходной таблицы на &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; влево. Тогда в столбце &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; будут находиться символы, добавленные на первом шаге алгоритма, а в столбце &amp;lt;tex&amp;gt;n - 1&amp;lt;/tex&amp;gt; символы, изначально стоявшие в таблице до первого шага алгоритма. Таким образом, полученные на первом шаге алгоритма строки являются суффиксами циклических перестановок строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Предположение. Пусть на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; шаге алгоритма все полученные строки являются суффиксами циклических перестановок строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Переход. Рассмотрим &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ый шаг алгоритма. Все строки отсортированы, поэтому самый левый столбец совпадет с &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; столбцом исходной таблицы. Циклически сдвинем все строки исходной таблицы на &amp;lt;tex&amp;gt;n - k&amp;lt;/tex&amp;gt; символов вправо. Теперь по предположению первые &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; символов справа в каждой строке совпадают у исходной таблицы и у таблицы, полученной в результате работы алгоритма. &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;-ые справа столбцы также совпадают. Добавленный на &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ом шаге столбец также совпадает с &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ым справа столбцом сдвинутой исходной таблицы, так как совпадает с последним столбцом исходной таблицы, которая была сдвинута на &amp;lt;tex&amp;gt;n-k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;3&amp;quot; | &amp;lt;tex&amp;gt;$k+1$&amp;lt;/tex&amp;gt; шаг алгоритма при &amp;lt;tex&amp;gt;$k=3$&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! Исходная &amp;lt;br /&amp;gt; таблица || Сдвинутая &amp;lt;br /&amp;gt; таблица || Результат &amp;lt;br /&amp;gt; работы &amp;lt;br /&amp;gt; алгоритма&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;CA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt;BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt;AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt;AA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt;AC&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt;BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:center;&amp;quot;|&lt;br /&gt;
CA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
AA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
AC&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:right;&amp;quot;|&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Таким образом, поскольку на каждом шаге алгоритма получившиеся строки являлись суффиксами циклических перестановок &amp;lt;tex&amp;gt; $s$ &amp;lt;/tex&amp;gt;, после последнего шага получившиеся строки будут совпадать с циклическими перестановками &amp;lt;tex&amp;gt; $s$ &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Оптимизированный наивный алгоритм===&lt;br /&gt;
&lt;br /&gt;
Наивный алгоритм можно оптимизировать. Заметим, что при каждом проявлении неизвестного столбца выполнялись одни и те же действия. Мы приписывали новый столбец и сортировали имеющиеся данные. На каждом шагу мы к строке, которая находилась на &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;-ом месте приписываем в начало &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; -ый элемент столбца входных данных. Пусть изначально мы знаем каким по порядку является приписанный нами в начало символ (то есть каким по порядку в столбце). И конечно же мы знаем исходя из предыдущего шага какое место занимала наша строка без этого первого символа (&amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; -ое). Тогда несложно заметить, что при выполнении такой операции строка с номером &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; всегда будет перемещаться на позицию с номером &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |0||а||&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;||р||9&lt;br /&gt;
  |-&lt;br /&gt;
  |1||а||||д||7&lt;br /&gt;
  |-&lt;br /&gt;
  |2||а|| ||a||0&lt;br /&gt;
  |-&lt;br /&gt;
  |3||а|| ||к||8&lt;br /&gt;
  |-&lt;br /&gt;
  |4||а|| ||р||10&lt;br /&gt;
  |-&lt;br /&gt;
  |5||б|| ||a||1&lt;br /&gt;
  |-&lt;br /&gt;
  |6||б|| ||a||2&lt;br /&gt;
  |-&lt;br /&gt;
  |7||д|| ||a||3&lt;br /&gt;
  |-&lt;br /&gt;
  |8||к|| ||a||4&lt;br /&gt;
  |-&lt;br /&gt;
  |9||р|| ||б||5&lt;br /&gt;
  |-&lt;br /&gt;
  |10||р|| ||б||6&lt;br /&gt;
  |}&lt;br /&gt;
&lt;br /&gt;
Здесь слева отсортированный данный столбец, чтобы мы знали, какое место в лексикографическом порядке занимает приписываемый нами символ среди всех элементов данного нам изначально столбца. Справа - изначально данный столбец и соответствующее ему число. Поскольку в нашем алгоритме новый столбец приписывается в начало, то мы из состояния &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; (левый столбец) переходим в состояние &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; (правый). Для того, чтобы восстановить строку, нам необходимо от последней такой цифры по пути из &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; восстановить строку.&lt;br /&gt;
{|&lt;br /&gt;
 |&lt;br /&gt;
 {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
 |6&lt;br /&gt;
 |→&lt;br /&gt;
 |10&lt;br /&gt;
 |→&lt;br /&gt;
 |4 &lt;br /&gt;
 |→&lt;br /&gt;
 |8&lt;br /&gt;
 |→ &lt;br /&gt;
 |3&lt;br /&gt;
 |→&lt;br /&gt;
 |7&lt;br /&gt;
 |→&lt;br /&gt;
 |1&lt;br /&gt;
 |→&lt;br /&gt;
 |5&lt;br /&gt;
 |→&lt;br /&gt;
 |9&lt;br /&gt;
 |→&lt;br /&gt;
 |0&lt;br /&gt;
 |→&lt;br /&gt;
 |2&lt;br /&gt;
 |-&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |б&lt;br /&gt;
 |&lt;br /&gt;
 |р&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |к&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |д&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |б&lt;br /&gt;
 |&lt;br /&gt;
 |р&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
|}&lt;br /&gt;
====Сложность оптимизированного алгоритма====&lt;br /&gt;
Данный алгоритм работает за &amp;lt;tex&amp;gt;O(N\log{N})&amp;lt;/tex&amp;gt; времени и требует &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt; памяти. Однако, если размер алфавита не очень большой, то для выяснения первого столбца матрицы можно использовать сортировку подсчетом, в этом случае алгоритм работает за &amp;lt;tex&amp;gt;O(N+M)&amp;lt;/tex&amp;gt; действий и требует &amp;lt;tex&amp;gt;O(N+M)&amp;lt;/tex&amp;gt; памяти, где &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; — размер алфавита.&lt;br /&gt;
&lt;br /&gt;
====Псевдокод оптимизированного алгоритма====&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; N &amp;lt;/tex&amp;gt; — количество символов во входной строке, &amp;lt;tex&amp;gt; M &amp;lt;/tex&amp;gt; — количество символов в алфавите, &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; — номер исходной строки в матрице перестановок, &amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt; — входящая строка, &amp;lt;tex&amp;gt; count &amp;lt;/tex&amp;gt;  — массив для сортировки подсчетом, &amp;lt;tex&amp;gt; t &amp;lt;/tex&amp;gt; — вектор обратного преобразования, &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; — номер данной нам строки в таблице.&lt;br /&gt;
&lt;br /&gt;
 // Cчитаем частоты символов&lt;br /&gt;
 '''for''' i = 0 .. M &lt;br /&gt;
   count[i] = 0&lt;br /&gt;
 '''for''' i = 0 .. N &lt;br /&gt;
   count[s[i]]++&lt;br /&gt;
 // Упорядочиваем символы, чтобы получить первый столбец исходной матрицы&lt;br /&gt;
 // count[i] указывает на первую позицию символа i в первом столбце&lt;br /&gt;
 sum = 0&lt;br /&gt;
 '''for''' i = 0 .. M&lt;br /&gt;
   sum = sum + count[i]&lt;br /&gt;
   count[i] = sum - count[i]&lt;br /&gt;
 // Cоздаем вектор обратного преобразования&lt;br /&gt;
 '''for''' i = 0 .. N&lt;br /&gt;
   t[count[s[i]]] = i&lt;br /&gt;
   count[s[i]]++&lt;br /&gt;
 // И восстанавливаем исходный текст&lt;br /&gt;
 j = t[x]&lt;br /&gt;
 '''for''' i = 0 .. N&lt;br /&gt;
   '''print'''(s[j])&lt;br /&gt;
   j = t[j]&lt;br /&gt;
&lt;br /&gt;
====Доказательство корректности====&lt;br /&gt;
&lt;br /&gt;
Пусть текст &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; состоит из &amp;lt;tex&amp;gt;N + 1&amp;lt;/tex&amp;gt; символов, занумерованных с нуля: &amp;lt;tex&amp;gt;T[0..N]&amp;lt;/tex&amp;gt;. Буквы &amp;lt;tex&amp;gt;T[i]&amp;lt;/tex&amp;gt; принадлежат некоторому алфавиту &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Лексикографический порядок (строгий) на строках из алфавита &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; будем обозначать &amp;lt;tex&amp;gt;\preceq (\prec)&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt;S_{k}T&amp;lt;/tex&amp;gt; циклический сдвиг текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; символов влево:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt; S_{k}T = T[(j + k) (mod\ N + 1)] &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Существует перестановка &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;\{0, ..., N\}&amp;lt;/tex&amp;gt;, которая удовлетворяет условию: &lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt; S_{p(i)}T \preceq S_{p(i + 1)}T,\ i = 0, ..., N - 1\ \ \textbf{(1)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Преобразование Барроуза-Уилера текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; есть текст &amp;lt;tex&amp;gt;B[0..N] = BW(T)&amp;lt;/tex&amp;gt;, буквы которого заданы соотношением:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt;B[i] = S_{p(i)}T[N]&amp;lt;/tex&amp;gt;, другими словами &amp;lt;tex&amp;gt;B[i] = S_{p(i) - 1}T[0] = T[(p(i) - 1) (mod\ N + 1)] \ \ \textbf{(2)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} перестановка чисел &amp;lt;tex&amp;gt;\{0, ..., N\}&amp;lt;/tex&amp;gt;, удовлетворяющая условию:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt;B_{\sigma(i)} \preceq B_{\sigma(i + 1)}&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N - 1\ \ \textbf{(3)}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
|}&lt;br /&gt;
и в случае равенства &amp;lt;tex&amp;gt;B_{\sigma(i)}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;B_{\sigma(i + 1)}&amp;lt;/tex&amp;gt; выполнено {{---}} &amp;lt;tex&amp;gt;\sigma(i) &amp;lt; \sigma(i + 1)&amp;lt;/tex&amp;gt;. Перестановка однозначно определяется текстом &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; и ее можно посчитать за &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt;, используя сортировку подсчетом. Рассмотрим перестановку &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; как отображение &amp;lt;tex&amp;gt;\sigma : \{0, ..., N\} \to \{0, ..., N\}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;\sigma^{k}&amp;lt;/tex&amp;gt; копмозиция &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; отображений &amp;lt;tex&amp;gt;\sigma^{k} = \sigma^{k - 1} \circ \sigma&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\sigma^{1} = \sigma, \sigma^{0} \equiv i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
&lt;br /&gt;
''При всех &amp;lt;tex&amp;gt;m = 1, ..., N + 1&amp;lt;/tex&amp;gt; верны утверждения,&lt;br /&gt;
:&amp;lt;tex&amp;gt;B_{\sigma(i)}...B_{\sigma^{m}(i)} \preceq B_{\sigma(i + 1)}...B_{\sigma^{m}(i + 1)}&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N - 1\ \ \textbf{(4)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;B_iB_{\sigma(i)}...B_{\sigma^{m - 1}(i)} = S_{p(i) - 1}T[0..m - 1]&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N\ \ \textbf{(5)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
|proof=&lt;br /&gt;
&lt;br /&gt;
Если лексикографически отсортировать буквы последнего столбца и поместить их в первый столбец, то получится таблица&lt;br /&gt;
&lt;br /&gt;
| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Таблица&lt;br /&gt;
|-&lt;br /&gt;
|a||b||c&lt;br /&gt;
|-&lt;br /&gt;
|a||b||c&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
&lt;br /&gt;
''Для восстановления исходного текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из преобразования &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; достаточно знать число &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;, отвечающее условию &amp;lt;tex&amp;gt;p(I) = 0&amp;lt;/tex&amp;gt;, другими словами &amp;lt;tex&amp;gt;S_{p(I)}T = T&amp;lt;/tex&amp;gt;.''&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Алгоритм за линейное время===&lt;br /&gt;
&lt;br /&gt;
Будем обозначать &amp;lt;tex&amp;gt;s^i&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ую циклическую перестановку &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;s^0 = s_0 s_1 \ldots s_{n-1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;$BWT(s)$\;= L&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;L = L_0L_1\ldots L_{n-1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; - номер строки &amp;lt;tex&amp;gt;s^0&amp;lt;/tex&amp;gt; в таблице. Предподсчитаем следующие величины:&lt;br /&gt;
* Для каждого &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt; количество символов на подстроке &amp;lt;tex&amp;gt;L_0 \ldots L_{i-1}&amp;lt;/tex&amp;gt;, равных &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
* Для каждого уникального &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt; количество символов в &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;, лексикографически меньших, чем &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пример для &amp;lt;tex&amp;gt;$BWT(s) =$&amp;lt;/tex&amp;gt; &amp;quot;BCABAAA&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
!colspan=&amp;quot;3&amp;quot; | Таблица первого предподсчёта&lt;br /&gt;
|-&lt;br /&gt;
! Позиция || Символ || Результат&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
! 0 || B || 0&lt;br /&gt;
|-&lt;br /&gt;
! 1 || C || 0&lt;br /&gt;
|-&lt;br /&gt;
! 2 || A || 0&lt;br /&gt;
|-&lt;br /&gt;
! 3 || B || 1&lt;br /&gt;
|-&lt;br /&gt;
! 4 || A || 1&lt;br /&gt;
|-&lt;br /&gt;
! 5 || A || 2&lt;br /&gt;
|-&lt;br /&gt;
! 6 || A || 3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; | Таблица второго предподсчёта&lt;br /&gt;
|-&lt;br /&gt;
! Символ || Количество  &amp;lt;br /&amp;gt; меньших&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
! A || 0&lt;br /&gt;
|-&lt;br /&gt;
! B || 4&lt;br /&gt;
|-&lt;br /&gt;
! C || 6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Для удобства пронумеруем известные нам данные:&lt;br /&gt;
# &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;, последний столбец таблицы перестановок&lt;br /&gt;
# &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;, номер строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt; в таблице перестановок&lt;br /&gt;
# Частота, с которой символ &amp;lt;tex&amp;gt;L_{i}&amp;lt;/tex&amp;gt; встречается в подстроке &amp;lt;tex&amp;gt;L_0\ldots L_{i-1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
# Для каждого уникального символа количество лексикографически меньших символов в &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Символ &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt; находится в строке &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; под номером &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;, так как в таблице строка &amp;lt;tex&amp;gt;s^0&amp;lt;/tex&amp;gt; имела номер &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;. Найдём символ &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Символ &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt; имеет в строке &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; тот же номер, что строка &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt; имела в таблице перестановок: строка &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt; начинается с символа &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt; находится на 1 левее его и из-за циклического сдвига оказывается в последнем столбце. Нам известен символ &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;. Посчитаем, на каком месте в таблице будет стоять строка, начинающаяся с этого символа.&lt;br /&gt;
&lt;br /&gt;
Из 4 известно количество символов, меньших &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;. Все строки, начинающиеся с этих символов, стоят в таблице раньше &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt;. Кроме того, в таблице есть строки, начинающиеся с того же символа, что и &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt;. Из 3 известно, сколько их: если символ, равный &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, встречался в &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; раньше, чем &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, то в таблице строка, начинающаяся с этого символа, тоже стоит раньше строки, начинающейся с &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, так как префикс строки, оканчивающейся на этот символ, меньше префикса строки, оканчивающейся на &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Тогда сумма этих двух величин является номером символа &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt; в строке &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;. Зная &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt;, аналогично найдём &amp;lt;tex&amp;gt;s_{n-3}\ldots s_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предподсчёт занимает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени, восстановление каждого из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; символов занимает &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; времени. Суммарное время работы алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пример работы для &amp;lt;tex&amp;gt;$BWT(s) = ($&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, 2&amp;lt;tex&amp;gt;)&amp;lt;/tex&amp;gt; (нумерация с 0):&lt;br /&gt;
* &amp;lt;tex&amp;gt;s^0 = .......&amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;s_6=L_2 = A&amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt;s^0=......&amp;lt;/tex&amp;gt;A&lt;br /&gt;
* Суммируем значения из двух таблиц: &amp;lt;tex&amp;gt;0+0=0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_5=L_0=B&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=.....&amp;lt;/tex&amp;gt;BA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;0+4=4&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_4=L_4=A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=....&amp;lt;/tex&amp;gt;ABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;1+0=1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_3=L_1=C&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=...&amp;lt;/tex&amp;gt;CABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;0+6=6&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_2=L_6=A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=..&amp;lt;/tex&amp;gt;ACABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;3+0=3&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_2=L_3=B&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=.&amp;lt;/tex&amp;gt;BACABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;1+4=5&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_2=L_5=A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=&amp;lt;/tex&amp;gt; ABACABA&lt;br /&gt;
&lt;br /&gt;
== Дополнительно ==&lt;br /&gt;
&lt;br /&gt;
* bzip2 использует преобразование Барроуза {{---}} Уилера для превращения последовательностей многократно чередующихся символов в строки одинаковых символов, затем применяет преобразование MTF (англ. move-to-front), и в конце кодирование Хаффмана.&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
*[http://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0_%E2%80%94_%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0 Википедия: Преобразование Барроуза {{---}} Уилера]&lt;br /&gt;
&lt;br /&gt;
*[http://www.cs.karelia.ru/~aborod/inf/2010/schedule.php.ru cs.karelia.ru: Преобразование Барроуза {{---}} Уилера]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы сжатия ]]&lt;/div&gt;</summary>
		<author><name>Evarand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0-%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0&amp;diff=50158</id>
		<title>Преобразование Барроуза-Уилера</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0-%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0&amp;diff=50158"/>
				<updated>2015-12-06T19:12:42Z</updated>
		
		<summary type="html">&lt;p&gt;Evarand: Косметические исправления&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Определение ==&lt;br /&gt;
&lt;br /&gt;
'''Преобразование Барроуза {{---}} Уилера''' (англ. ''Burrows-Wheeler transform'') {{---}} алгоритм, используемый для предварительной обработки данных перед сжатием, разработанный для улучшения эффективности последующего кодирования. Преобразование Барроуза {{---}} Уилера меняет порядок символов во входной строке таким образом, что повторяющиеся подстроки образуют на выходе идущие подряд последовательности одинаковых символов.&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Преобразование выполняется в три этапа. &lt;br /&gt;
* Составляется таблица всех циклических сдвигов входной строки.&lt;br /&gt;
* Производится лексикографическая (в алфавитном порядке) сортировка строк таблицы.&lt;br /&gt;
* В качестве выходной строки выбирается последний столбец таблицы преобразования и номер строки, совпадающей с исходной.&lt;br /&gt;
&lt;br /&gt;
== Пример работы алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дана исходная строка &amp;lt;tex&amp;gt;$s =$&amp;lt;/tex&amp;gt; &amp;quot;ABACABA&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;4&amp;quot;|Трансформация&lt;br /&gt;
|-&lt;br /&gt;
! Вход || Все&amp;lt;br /&amp;gt;Перестановки || Сортировка&amp;lt;br /&amp;gt;Строк || Выход&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
 BACABAA&lt;br /&gt;
 ACABAAB&lt;br /&gt;
 CABAABA&lt;br /&gt;
 ABAABAC&lt;br /&gt;
 BAABACA&lt;br /&gt;
 AABACAB&lt;br /&gt;
|&lt;br /&gt;
 AABACAB&lt;br /&gt;
 ABAABAC&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
 ACABAAB&lt;br /&gt;
 BAABACA&lt;br /&gt;
 BACABAA&lt;br /&gt;
 CABAABA &lt;br /&gt;
|&lt;br /&gt;
 BCABAAA, 3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Результат можно записать так: &amp;lt;tex&amp;gt;$BWT(s) = $(&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, &amp;lt;tex&amp;gt;3)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; {{---}} номер исходной строки в отсортированной матрице. Он нужен для обратного преобразования. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следует заметить, что иногда в исходной строке приводится так называемый символ конца строки &amp;lt;tex&amp;gt;\$&amp;lt;/tex&amp;gt;, который в преобразовании будет считаться последним (максимальным) символом, тогда сохранение номера исходной строки не требуется.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пусть нам дана исходная строка &amp;lt;tex&amp;gt;$s =$&amp;lt;/tex&amp;gt; &amp;quot;ABACABA$&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;4&amp;quot;|Трансформация&lt;br /&gt;
|-&lt;br /&gt;
! Вход || Все&amp;lt;br /&amp;gt;Перестановки || Сортировка&amp;lt;br /&amp;gt;Строк || Выход&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&lt;br /&gt;
 BACABA$A&lt;br /&gt;
 ACABA$AB&lt;br /&gt;
 CABA$ABA&lt;br /&gt;
 ABA$ABAC&lt;br /&gt;
 BA$ABACA&lt;br /&gt;
 A$ABACAB&lt;br /&gt;
 $ABACABA&lt;br /&gt;
&lt;br /&gt;
|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&lt;br /&gt;
 ABA$ABAC&lt;br /&gt;
 ACABA$AB&lt;br /&gt;
 A$ABACAB&lt;br /&gt;
 BACABA$A&lt;br /&gt;
 BA$ABACA&lt;br /&gt;
 CABA$ABA &lt;br /&gt;
 $ABACABA&lt;br /&gt;
|&lt;br /&gt;
 $CBBAAAA&lt;br /&gt;
|} &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
При аналогичном вышеприведённом преобразовании та строчка в матрице, которая будет заканчиваться на символ конца строки, и будет исходной: (&amp;quot;ABACABA$&amp;quot;). Тогда результат можно записать так: &amp;lt;tex&amp;gt;$BWT(s) =$&amp;lt;/tex&amp;gt; &amp;quot;$CBBAAAA&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Обратное преобразование ==&lt;br /&gt;
&lt;br /&gt;
===Наивный алгоритм===&lt;br /&gt;
&lt;br /&gt;
Пусть нам дано: &amp;lt;tex&amp;gt;$BWT(s) =$(&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, &amp;lt;tex&amp;gt;3)&amp;lt;/tex&amp;gt;. Тогда выпишем в столбик нашу преобразованную последовательность символов &amp;quot;BCABAAA&amp;quot;. Запишем её как последний столбик предыдущей матрицы (при прямом преобразовании Барроуза {{---}} Уилера), при этом все предыдущие столбцы оставляем пустыми. Далее построчно отсортируем матрицу, затем в предыдущий столбец запишем &amp;quot;BCABAAA&amp;quot;. Опять построчно отсортируем матрицу. Продолжая таким образом, можно восстановить полный список всех циклических перестановок строки, которую нам надо найти. Выстроив полный отсортированный список перестановок, выберем строку с номером, который нам был изначально дан. В итоге мы получим искомую строку.&lt;br /&gt;
Алгоритм обратного преобразования описан в таблице ниже:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Обратное преобразование&lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Вход&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot; colspan=&amp;quot;8&amp;quot;|&lt;br /&gt;
 BCABAAA&lt;br /&gt;
|-&lt;br /&gt;
! Добавление 1 || Сортировка 1 || Добавление 2 || Сортировка 2 || Добавление 3 || Сортировка 3 || Добавление 4 &lt;br /&gt;
|-align=&amp;quot;right&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
 B&lt;br /&gt;
 C&lt;br /&gt;
 A&lt;br /&gt;
 B&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
|&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 B&lt;br /&gt;
 B&lt;br /&gt;
 C&lt;br /&gt;
|&lt;br /&gt;
 BA&lt;br /&gt;
 CA&lt;br /&gt;
 AA&lt;br /&gt;
 BA&lt;br /&gt;
 AB&lt;br /&gt;
 AB&lt;br /&gt;
 AC&lt;br /&gt;
|&lt;br /&gt;
 AA&lt;br /&gt;
 AB&lt;br /&gt;
 AB&lt;br /&gt;
 AC&lt;br /&gt;
 BA&lt;br /&gt;
 BA&lt;br /&gt;
 CA&lt;br /&gt;
|&lt;br /&gt;
 BAA&lt;br /&gt;
 CAB&lt;br /&gt;
 AAB&lt;br /&gt;
 BAC&lt;br /&gt;
 ABA&lt;br /&gt;
 ABA&lt;br /&gt;
 ACA&lt;br /&gt;
|&lt;br /&gt;
 AAB&lt;br /&gt;
 ABA&lt;br /&gt;
 ABA&lt;br /&gt;
 ACA&lt;br /&gt;
 BAA&lt;br /&gt;
 BAC&lt;br /&gt;
 CAB&lt;br /&gt;
|&lt;br /&gt;
 BAAB&lt;br /&gt;
 CABA&lt;br /&gt;
 AABA&lt;br /&gt;
 BACA&lt;br /&gt;
 ABAA&lt;br /&gt;
 ABAC&lt;br /&gt;
 ACAB&lt;br /&gt;
|-&lt;br /&gt;
! Сортировка 4 || Добавление 5 || Сортировка 5 || Добавление 6 || Сортировка 6 || Добавление 7 || Сортировка 7&lt;br /&gt;
&lt;br /&gt;
|-align=&amp;quot;right&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
 AABA&lt;br /&gt;
 ABAA&lt;br /&gt;
 ABAC&lt;br /&gt;
 ACAB&lt;br /&gt;
 BAAB&lt;br /&gt;
 BACA&lt;br /&gt;
 CABA&lt;br /&gt;
|&lt;br /&gt;
 BAABA&lt;br /&gt;
 CABAA&lt;br /&gt;
 AABAC&lt;br /&gt;
 BACAB&lt;br /&gt;
 ABAAB&lt;br /&gt;
 ABACA&lt;br /&gt;
 ACABA&lt;br /&gt;
|&lt;br /&gt;
 AABAC&lt;br /&gt;
 ABAAB&lt;br /&gt;
 ABACA&lt;br /&gt;
 ACABA&lt;br /&gt;
 BAABA&lt;br /&gt;
 BACAB&lt;br /&gt;
 CABAA&lt;br /&gt;
|&lt;br /&gt;
 BAABAC&lt;br /&gt;
 CABAAB&lt;br /&gt;
 AABACA&lt;br /&gt;
 BACABA&lt;br /&gt;
 ABAABA&lt;br /&gt;
 ABACAB&lt;br /&gt;
 ACABAA&lt;br /&gt;
|&lt;br /&gt;
 AABACA&lt;br /&gt;
 ABAABA&lt;br /&gt;
 ABACAB&lt;br /&gt;
 ACABAA&lt;br /&gt;
 BAABAC&lt;br /&gt;
 BACABA&lt;br /&gt;
 CABAAB&lt;br /&gt;
|&lt;br /&gt;
 BAABACA&lt;br /&gt;
 CABAABA&lt;br /&gt;
 AABACAB&lt;br /&gt;
 BACABAA&lt;br /&gt;
 ABAABAC&lt;br /&gt;
 ABACABA&lt;br /&gt;
 ACABAAB&lt;br /&gt;
|&lt;br /&gt;
 AABACAB&lt;br /&gt;
 ABAABAC&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
 ACABAAB&lt;br /&gt;
 BAABACA&lt;br /&gt;
 BACABAA&lt;br /&gt;
 CABAABA&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Результат&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot; colspan=&amp;quot;8&amp;quot;|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Следует также заметить, что если нам было бы дано &amp;lt;tex&amp;gt;$BWT(s) = $&amp;lt;/tex&amp;gt; &amp;quot;$CBBAAAA&amp;quot;, то мы также получили бы нашу исходную строку, только с символом конца строки &amp;lt;tex&amp;gt;\$&amp;lt;/tex&amp;gt; на конце: ABACABA$.&lt;br /&gt;
&lt;br /&gt;
Временная сложность данного алгоритма &amp;lt;tex&amp;gt;O(N^3\log{N}) &amp;lt;/tex&amp;gt;, пространственная &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Доказательство корректности====&lt;br /&gt;
&lt;br /&gt;
Пусть дана строка &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;, к которой было применено преобразование BWT. Докажем, что при использовании наивного алгоритма на каждом шаге получающийся набор строк соответствует суффиксам циклических перестановок исходной строки, методом математической индукции.&lt;br /&gt;
* База. Циклически сдвинем все строки исходной таблицы на &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; влево. Тогда в столбце &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; будут находиться символы, добавленные на первом шаге алгоритма, а в столбце &amp;lt;tex&amp;gt;n - 1&amp;lt;/tex&amp;gt; символы, изначально стоявшие в таблице до первого шага алгоритма. Таким образом, полученные на первом шаге алгоритма строки являются суффиксами циклических перестановок строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Предположение. Пусть на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; шаге алгоритма все полученные строки являются суффиксами циклических перестановок строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Переход. Рассмотрим &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ый шаг алгоритма. Все строки отсортированы, поэтому самый левый столбец совпадет с &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; столбцом исходной таблицы. Циклически сдвинем все строки исходной таблицы на &amp;lt;tex&amp;gt;n - k&amp;lt;/tex&amp;gt; символов вправо. Теперь по предположению первые &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; символов справа в каждой строке совпадают у исходной таблицы и у таблицы, полученной в результате работы алгоритма. &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;-ые справа столбцы также совпадают. Добавленный на &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ом шаге столбец также совпадает с &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ым справа столбцом сдвинутой исходной таблицы, так как совпадает с последним столбцом исходной таблицы, которая была сдвинута на &amp;lt;tex&amp;gt;n-k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{|border =&amp;quot;1&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;3&amp;quot; | &amp;lt;tex&amp;gt;$k+1$&amp;lt;/tex&amp;gt; шаг алгоритма при &amp;lt;tex&amp;gt;$k=3$&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! Исходная &amp;lt;br /&amp;gt; таблица || Сдвинутая &amp;lt;br /&amp;gt; таблица || Результат &amp;lt;br /&amp;gt; работы &amp;lt;br /&amp;gt; алгоритма&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;CA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt;BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt;AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt;AA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt;AC&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt;BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
 CA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;&lt;br /&gt;
 BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt;&lt;br /&gt;
 AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt;&lt;br /&gt;
 AA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt;&lt;br /&gt;
 AC&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt;&lt;br /&gt;
 BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt;&lt;br /&gt;
 AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Таким образом, поскольку на каждом шаге алгоритма получившиеся строки являлись суффиксами циклических перестановок &amp;lt;tex&amp;gt; $s$ &amp;lt;/tex&amp;gt;, после последнего шага получившиеся строки будут совпадать с циклическими перестановками &amp;lt;tex&amp;gt; $s$ &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Оптимизированный наивный алгоритм===&lt;br /&gt;
&lt;br /&gt;
Наивный алгоритм можно оптимизировать. Заметим, что при каждом проявлении неизвестного столбца выполнялись одни и те же действия. Мы приписывали новый столбец и сортировали имеющиеся данные. На каждом шагу мы к строке, которая находилась на &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;-ом месте приписываем в начало &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; -ый элемент столбца входных данных. Пусть изначально мы знаем каким по порядку является приписанный нами в начало символ (то есть каким по порядку в столбце). И конечно же мы знаем исходя из предыдущего шага какое место занимала наша строка без этого первого символа (&amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; -ое). Тогда несложно заметить, что при выполнении такой операции строка с номером &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; всегда будет перемещаться на позицию с номером &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 {| border=&amp;quot;1&amp;quot;&lt;br /&gt;
  |0||а||&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;||р||9&lt;br /&gt;
  |-&lt;br /&gt;
  |1||а||||д||7&lt;br /&gt;
  |-&lt;br /&gt;
  |2||а|| ||a||0&lt;br /&gt;
  |-&lt;br /&gt;
  |3||а|| ||к||8&lt;br /&gt;
  |-&lt;br /&gt;
  |4||а|| ||р||10&lt;br /&gt;
  |-&lt;br /&gt;
  |5||б|| ||a||1&lt;br /&gt;
  |-&lt;br /&gt;
  |6||б|| ||a||2&lt;br /&gt;
  |-&lt;br /&gt;
  |7||д|| ||a||3&lt;br /&gt;
  |-&lt;br /&gt;
  |8||к|| ||a||4&lt;br /&gt;
  |-&lt;br /&gt;
  |9||р|| ||б||5&lt;br /&gt;
  |-&lt;br /&gt;
  |10||р|| ||б||6&lt;br /&gt;
  |}&lt;br /&gt;
&lt;br /&gt;
Здесь слева отсортированный данный столбец, чтобы мы знали, какое место в лексикографическом порядке занимает приписываемый нами символ среди всех элементов данного нам изначально столбца. Справа - изначально данный столбец и соответствующее ему число. Поскольку в нашем алгоритме новый столбец приписывается в начало, то мы из состояния &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; (левый столбец) переходим в состояние &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; (правый). Для того, чтобы восстановить строку, нам необходимо от последней такой цифры по пути из &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; восстановить строку.&lt;br /&gt;
{|&lt;br /&gt;
 |&lt;br /&gt;
 {| border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |6&lt;br /&gt;
 |→&lt;br /&gt;
 |10&lt;br /&gt;
 |→&lt;br /&gt;
 |4 &lt;br /&gt;
 |→&lt;br /&gt;
 |8&lt;br /&gt;
 |→ &lt;br /&gt;
 |3&lt;br /&gt;
 |→&lt;br /&gt;
 |7&lt;br /&gt;
 |→&lt;br /&gt;
 |1&lt;br /&gt;
 |→&lt;br /&gt;
 |5&lt;br /&gt;
 |→&lt;br /&gt;
 |9&lt;br /&gt;
 |→&lt;br /&gt;
 |0&lt;br /&gt;
 |→&lt;br /&gt;
 |2&lt;br /&gt;
 |-&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |б&lt;br /&gt;
 |&lt;br /&gt;
 |р&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |к&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |д&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |б&lt;br /&gt;
 |&lt;br /&gt;
 |р&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
|}&lt;br /&gt;
====Сложность оптимизированного алгоритма====&lt;br /&gt;
Данный алгоритм работает за &amp;lt;tex&amp;gt;O(N\log{N})&amp;lt;/tex&amp;gt; времени и требует &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt; памяти. Однако, если размер алфавита не очень большой, то для выяснения первого столбца матрицы можно использовать сортировку подсчетом, в этом случае алгоритм работает за &amp;lt;tex&amp;gt;O(N+M)&amp;lt;/tex&amp;gt; действий и требует &amp;lt;tex&amp;gt;O(N+M)&amp;lt;/tex&amp;gt; памяти, где &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; — размер алфавита.&lt;br /&gt;
&lt;br /&gt;
====Псевдокод оптимизированного алгоритма====&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; N &amp;lt;/tex&amp;gt; — количество символов во входной строке, &amp;lt;tex&amp;gt; M &amp;lt;/tex&amp;gt; — количество символов в алфавите, &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; — номер исходной строки в матрице перестановок, &amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt; — входящая строка, &amp;lt;tex&amp;gt; count &amp;lt;/tex&amp;gt;  — массив для сортировки подсчетом, &amp;lt;tex&amp;gt; t &amp;lt;/tex&amp;gt; — вектор обратного преобразования, &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; — номер данной нам строки в таблице.&lt;br /&gt;
&lt;br /&gt;
 // Cчитаем частоты символов&lt;br /&gt;
 '''for''' i = 0 .. M &lt;br /&gt;
   count[i] = 0&lt;br /&gt;
 '''for''' i = 0 .. N &lt;br /&gt;
   count[s[i]]++&lt;br /&gt;
 // Упорядочиваем символы, чтобы получить первый столбец исходной матрицы&lt;br /&gt;
 // count[i] указывает на первую позицию символа i в первом столбце&lt;br /&gt;
 sum = 0&lt;br /&gt;
 '''for''' i = 0 .. M&lt;br /&gt;
   sum = sum + count[i]&lt;br /&gt;
   count[i] = sum - count[i]&lt;br /&gt;
 // Cоздаем вектор обратного преобразования&lt;br /&gt;
 '''for''' i = 0 .. N&lt;br /&gt;
   t[count[s[i]]] = i&lt;br /&gt;
   count[s[i]]++&lt;br /&gt;
 // И восстанавливаем исходный текст&lt;br /&gt;
 j = t[x]&lt;br /&gt;
 '''for''' i = 0 .. N&lt;br /&gt;
   '''print'''(s[j])&lt;br /&gt;
   j = t[j]&lt;br /&gt;
&lt;br /&gt;
====Доказательство корректности====&lt;br /&gt;
&lt;br /&gt;
Пусть текст &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; состоит из &amp;lt;tex&amp;gt;N + 1&amp;lt;/tex&amp;gt; символов, занумерованных с нуля: &amp;lt;tex&amp;gt;T[0..N]&amp;lt;/tex&amp;gt;. Буквы &amp;lt;tex&amp;gt;T[i]&amp;lt;/tex&amp;gt; принадлежат некоторому алфавиту &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Лексикографический порядок (строгий) на строках из алфавита &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; будем обозначать &amp;lt;tex&amp;gt;\preceq (\prec)&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt;S_{k}T&amp;lt;/tex&amp;gt; циклический сдвиг текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; символов влево:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt; S_{k}T = T[(j + k) (mod\ N + 1)] &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Существует перестановка &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;\{0, ..., N\}&amp;lt;/tex&amp;gt;, которая удовлетворяет условию: &lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt; S_{p(i)}T \preceq S_{p(i + 1)}T,\ i = 0, ..., N - 1\ \ \textbf{(1)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Преобразование Барроуза-Уилера текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; есть текст &amp;lt;tex&amp;gt;B[0..N] = BW(T)&amp;lt;/tex&amp;gt;, буквы которого заданы соотношением:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt;B[i] = S_{p(i)}T[N]&amp;lt;/tex&amp;gt;, другими словами &amp;lt;tex&amp;gt;B[i] = S_{p(i) - 1}T[0] = T[(p(i) - 1) (mod\ N + 1)] \ \ \textbf{(2)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} перестановка чисел &amp;lt;tex&amp;gt;\{0, ..., N\}&amp;lt;/tex&amp;gt;, удовлетворяющая условию:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt;B_{\sigma(i)} \preceq B_{\sigma(i + 1)}&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N - 1\ \ \textbf{(3)}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
|}&lt;br /&gt;
и в случае равенства &amp;lt;tex&amp;gt;B_{\sigma(i)}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;B_{\sigma(i + 1)}&amp;lt;/tex&amp;gt; выполнено {{---}} &amp;lt;tex&amp;gt;\sigma(i) &amp;lt; \sigma(i + 1)&amp;lt;/tex&amp;gt;. Перестановка однозначно определяется текстом &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; и ее можно посчитать за &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt;, используя сортировку подсчетом. Рассмотрим перестановку &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; как отображение &amp;lt;tex&amp;gt;\sigma : \{0, ..., N\} \to \{0, ..., N\}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;\sigma^{k}&amp;lt;/tex&amp;gt; копмозиция &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; отображений &amp;lt;tex&amp;gt;\sigma^{k} = \sigma^{k - 1} \circ \sigma&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\sigma^{1} = \sigma, \sigma^{0} \equiv i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
&lt;br /&gt;
''При всех &amp;lt;tex&amp;gt;m = 1, ..., N + 1&amp;lt;/tex&amp;gt; верны утверждения,&lt;br /&gt;
:&amp;lt;tex&amp;gt;B_{\sigma(i)}...B_{\sigma^{m}(i)} \preceq B_{\sigma(i + 1)}...B_{\sigma^{m}(i + 1)}&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N - 1\ \ \textbf{(4)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;B_iB_{\sigma(i)}...B_{\sigma^{m - 1}(i)} = S_{p(i) - 1}T[0..m - 1]&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N\ \ \textbf{(5)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
|proof=&lt;br /&gt;
&lt;br /&gt;
Если лексикографически отсортировать буквы последнего столбца и поместить их в первый столбец, то получится таблица&lt;br /&gt;
&lt;br /&gt;
| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Таблица&lt;br /&gt;
|-&lt;br /&gt;
|a||b||c&lt;br /&gt;
|-&lt;br /&gt;
|a||b||c&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
&lt;br /&gt;
''Для восстановления исходного текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из преобразования &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; достаточно знать число &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;, отвечающее условию &amp;lt;tex&amp;gt;p(I) = 0&amp;lt;/tex&amp;gt;, другими словами &amp;lt;tex&amp;gt;S_{p(I)}T = T&amp;lt;/tex&amp;gt;.''&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Алгоритм за линейное время===&lt;br /&gt;
&lt;br /&gt;
Будем обозначать &amp;lt;tex&amp;gt;s^i&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ую циклическую перестановку &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;s^0 = s_0 s_1 \ldots s_{n-1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;$BWT(s)$\;= L&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;L = L_0L_1\ldots L_{n-1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; - номер строки &amp;lt;tex&amp;gt;s^0&amp;lt;/tex&amp;gt; в таблице. Предподсчитаем следующие величины:&lt;br /&gt;
* Для каждого &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt; количество символов на подстроке &amp;lt;tex&amp;gt;L_0 \ldots L_{i-1}&amp;lt;/tex&amp;gt;, равных &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
* Для каждого уникального &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt; количество символов в &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;, лексикографически меньших, чем &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пример для &amp;lt;tex&amp;gt;$BWT(s) =$&amp;lt;/tex&amp;gt; &amp;quot;BCABAAA&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
{|border =&amp;quot;1&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;3&amp;quot; | Таблица первого предподсчёта&lt;br /&gt;
|-&lt;br /&gt;
! Позиция || Символ || Результат&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
! 0 || B || 0&lt;br /&gt;
|-&lt;br /&gt;
! 1 || C || 0&lt;br /&gt;
|-&lt;br /&gt;
! 2 || A || 0&lt;br /&gt;
|-&lt;br /&gt;
! 3 || B || 1&lt;br /&gt;
|-&lt;br /&gt;
! 4 || A || 1&lt;br /&gt;
|-&lt;br /&gt;
! 5 || A || 2&lt;br /&gt;
|-&lt;br /&gt;
! 6 || A || 3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|border =&amp;quot;1&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; | Таблица второго предподсчёта&lt;br /&gt;
|-&lt;br /&gt;
! Символ || Количество  &amp;lt;br /&amp;gt; меньших&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
! A || 0&lt;br /&gt;
|-&lt;br /&gt;
! B || 4&lt;br /&gt;
|-&lt;br /&gt;
! C || 6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Для удобства пронумеруем известные нам данные:&lt;br /&gt;
# &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;, последний столбец таблицы перестановок&lt;br /&gt;
# &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;, номер строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt; в таблице перестановок&lt;br /&gt;
# Частота, с которой символ &amp;lt;tex&amp;gt;L_{i}&amp;lt;/tex&amp;gt; встречается в подстроке &amp;lt;tex&amp;gt;L_0\ldots L_{i-1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
# Для каждого уникального символа количество лексикографически меньших символов в &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Символ &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt; находится в строке &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; под номером &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;, так как в таблице строка &amp;lt;tex&amp;gt;s^0&amp;lt;/tex&amp;gt; имела номер &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;. Найдём символ &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Символ &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt; имеет в строке &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; тот же номер, что строка &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt; имела в таблице перестановок: строка &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt; начинается с символа &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt; находится на 1 левее его и из-за циклического сдвига оказывается в последнем столбце. Нам известен символ &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;. Посчитаем, на каком месте в таблице будет стоять строка, начинающаяся с этого символа.&lt;br /&gt;
&lt;br /&gt;
Из 4 известно количество символов, меньших &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;. Все строки, начинающиеся с этих символов, стоят в таблице раньше &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt;. Кроме того, в таблице есть строки, начинающиеся с того же символа, что и &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt;. Из 3 известно, сколько их: если символ, равный &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, встречался в &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; раньше, чем &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, то в таблице строка, начинающаяся с этого символа, тоже стоит раньше строки, начинающейся с &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, так как префикс строки, оканчивающейся на этот символ, меньше префикса строки, оканчивающейся на &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Тогда сумма этих двух величин является номером символа &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt; в строке &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;. Зная &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt;, аналогично найдём &amp;lt;tex&amp;gt;s_{n-3}\ldots s_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предподсчёт занимает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени, восстановление каждого из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; символов занимает &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; времени. Суммарное время работы алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пример работы для &amp;lt;tex&amp;gt;$BWT(s) = ($&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, 2&amp;lt;tex&amp;gt;)&amp;lt;/tex&amp;gt; (нумерация с 0):&lt;br /&gt;
* &amp;lt;tex&amp;gt;s^0 = .......&amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;s_6=L_2 = A&amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt;s^0=......&amp;lt;/tex&amp;gt;A&lt;br /&gt;
* Суммируем значения из двух таблиц: &amp;lt;tex&amp;gt;0+0=0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_5=L_0=B&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=.....&amp;lt;/tex&amp;gt;BA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;0+4=4&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_4=L_4=A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=....&amp;lt;/tex&amp;gt;ABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;1+0=1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_3=L_1=C&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=...&amp;lt;/tex&amp;gt;CABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;0+6=6&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_2=L_6=A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=..&amp;lt;/tex&amp;gt;ACABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;3+0=3&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_2=L_3=B&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=.&amp;lt;/tex&amp;gt;BACABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;1+4=5&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_2=L_5=A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=&amp;lt;/tex&amp;gt; ABACABA&lt;br /&gt;
&lt;br /&gt;
== Дополнительно ==&lt;br /&gt;
&lt;br /&gt;
* bzip2 использует преобразование Барроуза {{---}} Уилера для превращения последовательностей многократно чередующихся символов в строки одинаковых символов, затем применяет преобразование MTF (англ. move-to-front), и в конце кодирование Хаффмана.&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
*[http://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0_%E2%80%94_%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0 Википедия: Преобразование Барроуза {{---}} Уилера]&lt;br /&gt;
&lt;br /&gt;
*[http://www.cs.karelia.ru/~aborod/inf/2010/schedule.php.ru cs.karelia.ru: Преобразование Барроуза {{---}} Уилера]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы сжатия ]]&lt;/div&gt;</summary>
		<author><name>Evarand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0-%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0&amp;diff=50153</id>
		<title>Преобразование Барроуза-Уилера</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0-%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0&amp;diff=50153"/>
				<updated>2015-12-06T17:22:40Z</updated>
		
		<summary type="html">&lt;p&gt;Evarand: Алгоритм за O(n)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Определение ==&lt;br /&gt;
&lt;br /&gt;
'''Преобразование Барроуза {{---}} Уилера''' (англ. ''Burrows-Wheeler transform'') {{---}} алгоритм, используемый для предварительной обработки данных перед сжатием, разработанный для улучшения эффективности последующего кодирования. Преобразование Барроуза {{---}} Уилера меняет порядок символов во входной строке таким образом, что повторяющиеся подстроки образуют на выходе идущие подряд последовательности одинаковых символов.&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Преобразование выполняется в три этапа. &lt;br /&gt;
* Составляется таблица всех циклических сдвигов входной строки.&lt;br /&gt;
* Производится лексикографическая (в алфавитном порядке) сортировка строк таблицы.&lt;br /&gt;
* В качестве выходной строки выбирается последний столбец таблицы преобразования и номер строки, совпадающей с исходной.&lt;br /&gt;
&lt;br /&gt;
== Пример работы алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дана исходная строка &amp;lt;tex&amp;gt;$s =$&amp;lt;/tex&amp;gt; &amp;quot;ABACABA&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;4&amp;quot;|Трансформация&lt;br /&gt;
|-&lt;br /&gt;
! Вход || Все&amp;lt;br /&amp;gt;Перестановки || Сортировка&amp;lt;br /&amp;gt;Строк || Выход&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
 BACABAA&lt;br /&gt;
 ACABAAB&lt;br /&gt;
 CABAABA&lt;br /&gt;
 ABAABAC&lt;br /&gt;
 BAABACA&lt;br /&gt;
 AABACAB&lt;br /&gt;
|&lt;br /&gt;
 AABACAB&lt;br /&gt;
 ABAABAC&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
 ACABAAB&lt;br /&gt;
 BAABACA&lt;br /&gt;
 BACABAA&lt;br /&gt;
 CABAABA &lt;br /&gt;
|&lt;br /&gt;
 BCABAAA, 3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Результат можно записать так: &amp;lt;tex&amp;gt;$BWT(s) = $(&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, 3&amp;lt;tex&amp;gt;)&amp;lt;/tex&amp;gt;, где 3 {{---}} номер исходной строки в отсортированной матрице. Он нужен для обратного преобразования. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следует заметить, что иногда в исходной строке приводится так называемый символ конца строки ''$'', который в преобразовании будет считаться последним (максимальным) символом, тогда сохранение номера исходной строки не требуется.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пусть нам дана исходная строка &amp;lt;tex&amp;gt;$s =$&amp;lt;/tex&amp;gt; &amp;quot;ABACABA$&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;4&amp;quot;|Трансформация&lt;br /&gt;
|-&lt;br /&gt;
! Вход || Все&amp;lt;br /&amp;gt;Перестановки || Сортировка&amp;lt;br /&amp;gt;Строк || Выход&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&lt;br /&gt;
 BACABA$A&lt;br /&gt;
 ACABA$AB&lt;br /&gt;
 CABA$ABA&lt;br /&gt;
 ABA$ABAC&lt;br /&gt;
 BA$ABACA&lt;br /&gt;
 A$ABACAB&lt;br /&gt;
 $ABACABA&lt;br /&gt;
&lt;br /&gt;
|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&lt;br /&gt;
 ABA$ABAC&lt;br /&gt;
 ACABA$AB&lt;br /&gt;
 A$ABACAB&lt;br /&gt;
 BACABA$A&lt;br /&gt;
 BA$ABACA&lt;br /&gt;
 CABA$ABA &lt;br /&gt;
 $ABACABA&lt;br /&gt;
|&lt;br /&gt;
 $CBBAAAA&lt;br /&gt;
|} &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
При аналогичном вышеприведённом преобразовании та строчка в матрице, которая будет заканчиваться на символ конца строки, и будет исходной: (&amp;quot;ABACABA$&amp;quot;). Тогда результат можно записать так: &amp;lt;tex&amp;gt;$BWT(s) =$&amp;lt;/tex&amp;gt; &amp;quot;$CBBAAAA&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Обратное преобразование ==&lt;br /&gt;
&lt;br /&gt;
===Наивный алгоритм===&lt;br /&gt;
&lt;br /&gt;
Пусть нам дано: &amp;lt;tex&amp;gt;$BWT(s) =$(&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, 3&amp;lt;tex&amp;gt;)&amp;lt;/tex&amp;gt;. Тогда выпишем в столбик нашу преобразованную последовательность символов &amp;quot;BCABAAA&amp;quot;. Запишем её как последний столбик предыдущей матрицы (при прямом преобразовании Барроуза {{---}} Уилера), при этом все предыдущие столбцы оставляем пустыми. Далее построчно отсортируем матрицу, затем в предыдущий столбец запишем &amp;quot;BCABAAA&amp;quot;. Опять построчно отсортируем матрицу. Продолжая таким образом, можно восстановить полный список всех циклических перестановок строки, которую нам надо найти. Выстроив полный отсортированный список перестановок, выберем строку с номером, который нам был изначально дан. В итоге мы получим искомую строку.&lt;br /&gt;
Алгоритм обратного преобразования описан в таблице ниже:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Обратное преобразование&lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Вход&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot; colspan=&amp;quot;8&amp;quot;|&lt;br /&gt;
 BCABAAA&lt;br /&gt;
|-&lt;br /&gt;
! Добавление 1 || Сортировка 1 || Добавление 2 || Сортировка 2 || Добавление 3 || Сортировка 3 || Добавление 4 &lt;br /&gt;
|-align=&amp;quot;right&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
 B&lt;br /&gt;
 C&lt;br /&gt;
 A&lt;br /&gt;
 B&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
|&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 B&lt;br /&gt;
 B&lt;br /&gt;
 C&lt;br /&gt;
|&lt;br /&gt;
 BA&lt;br /&gt;
 CA&lt;br /&gt;
 AA&lt;br /&gt;
 BA&lt;br /&gt;
 AB&lt;br /&gt;
 AB&lt;br /&gt;
 AC&lt;br /&gt;
|&lt;br /&gt;
 AA&lt;br /&gt;
 AB&lt;br /&gt;
 AB&lt;br /&gt;
 AC&lt;br /&gt;
 BA&lt;br /&gt;
 BA&lt;br /&gt;
 CA&lt;br /&gt;
|&lt;br /&gt;
 BAA&lt;br /&gt;
 CAB&lt;br /&gt;
 AAB&lt;br /&gt;
 BAC&lt;br /&gt;
 ABA&lt;br /&gt;
 ABA&lt;br /&gt;
 ACA&lt;br /&gt;
|&lt;br /&gt;
 AAB&lt;br /&gt;
 ABA&lt;br /&gt;
 ABA&lt;br /&gt;
 ACA&lt;br /&gt;
 BAA&lt;br /&gt;
 BAC&lt;br /&gt;
 CAB&lt;br /&gt;
|&lt;br /&gt;
 BAAB&lt;br /&gt;
 CABA&lt;br /&gt;
 AABA&lt;br /&gt;
 BACA&lt;br /&gt;
 ABAA&lt;br /&gt;
 ABAC&lt;br /&gt;
 ACAB&lt;br /&gt;
|-&lt;br /&gt;
! Сортировка 4 || Добавление 5 || Сортировка 5 || Добавление 6 || Сортировка 6 || Добавление 7 || Сортировка 7&lt;br /&gt;
&lt;br /&gt;
|-align=&amp;quot;right&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
 AABA&lt;br /&gt;
 ABAA&lt;br /&gt;
 ABAC&lt;br /&gt;
 ACAB&lt;br /&gt;
 BAAB&lt;br /&gt;
 BACA&lt;br /&gt;
 CABA&lt;br /&gt;
|&lt;br /&gt;
 BAABA&lt;br /&gt;
 CABAA&lt;br /&gt;
 AABAC&lt;br /&gt;
 BACAB&lt;br /&gt;
 ABAAB&lt;br /&gt;
 ABACA&lt;br /&gt;
 ACABA&lt;br /&gt;
|&lt;br /&gt;
 AABAC&lt;br /&gt;
 ABAAB&lt;br /&gt;
 ABACA&lt;br /&gt;
 ACABA&lt;br /&gt;
 BAABA&lt;br /&gt;
 BACAB&lt;br /&gt;
 CABAA&lt;br /&gt;
|&lt;br /&gt;
 BAABAC&lt;br /&gt;
 CABAAB&lt;br /&gt;
 AABACA&lt;br /&gt;
 BACABA&lt;br /&gt;
 ABAABA&lt;br /&gt;
 ABACAB&lt;br /&gt;
 ACABAA&lt;br /&gt;
|&lt;br /&gt;
 AABACA&lt;br /&gt;
 ABAABA&lt;br /&gt;
 ABACAB&lt;br /&gt;
 ACABAA&lt;br /&gt;
 BAABAC&lt;br /&gt;
 BACABA&lt;br /&gt;
 CABAAB&lt;br /&gt;
|&lt;br /&gt;
 BAABACA&lt;br /&gt;
 CABAABA&lt;br /&gt;
 AABACAB&lt;br /&gt;
 BACABAA&lt;br /&gt;
 ABAABAC&lt;br /&gt;
 ABACABA&lt;br /&gt;
 ACABAAB&lt;br /&gt;
|&lt;br /&gt;
 AABACAB&lt;br /&gt;
 ABAABAC&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
 ACABAAB&lt;br /&gt;
 BAABACA&lt;br /&gt;
 BACABAA&lt;br /&gt;
 CABAABA&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Результат&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot; colspan=&amp;quot;8&amp;quot;|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Следует также заметить, что если нам было бы дано &amp;lt;tex&amp;gt;$BWT(s) = $&amp;lt;/tex&amp;gt; &amp;quot;$CBBAAAA&amp;quot;, то мы также получили бы нашу исходную строку, только с символом конца строки ''$'' на конце: ''ABACABA$''.&lt;br /&gt;
&lt;br /&gt;
Временная сложность данного алгоритма &amp;lt;tex&amp;gt;O(N^3\log{N}) &amp;lt;/tex&amp;gt;, пространственная &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Доказательство корректности====&lt;br /&gt;
&lt;br /&gt;
Пусть дана строка &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;, к которой было применено преобразование BWT. Докажем, что при использовании наивного алгоритма на каждом шаге получающийся набор строк соответствует суффиксам циклических перестановок исходной строки, методом математической индукции.&lt;br /&gt;
* База. Циклически сдвинем все строки исходной таблицы на 1 влево. Тогда в столбце &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; будут находиться символы, добавленные на первом шаге алгоритма, а в столбце &amp;lt;tex&amp;gt;n - 1&amp;lt;/tex&amp;gt; символы, изначально стоявшие в таблице до первого шага алгоритма. Таким образом, полученные на первом шаге алгоритма строки являются суффиксами циклических перестановок строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Предположение. Пусть на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; шаге алгоритма все полученные строки являются суффиксами циклических перестановок строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Переход. Рассмотрим &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ый шаг алгоритма. Все строки отсортированы, поэтому самый левый столбец совпадет с 1 столбцом исходной таблицы. Циклически сдвинем все строки исходной таблицы на &amp;lt;tex&amp;gt;n - k&amp;lt;/tex&amp;gt; символов вправо. Теперь по предположению первые &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; символов справа в каждой строке совпадают у исходной таблицы и у таблицы, полученной в результате работы алгоритма. &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;-ые справа столбцы также совпадают. Добавленный на &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ом шаге столбец также совпадает с &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ым справа столбцом сдвинутой исходной таблицы, так как совпадает с последним столбцом исходной таблицы, которая была сдвинута на &amp;lt;tex&amp;gt;n-k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{|border =&amp;quot;1&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;3&amp;quot; | &amp;lt;tex&amp;gt;$k+1$&amp;lt;/tex&amp;gt; шаг алгоритма при &amp;lt;tex&amp;gt;$k=3$&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! Исходная &amp;lt;br /&amp;gt; таблица || Сдвинутая &amp;lt;br /&amp;gt; таблица || Результат &amp;lt;br /&amp;gt; работы &amp;lt;br /&amp;gt; алгоритма&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;CA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt;BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt;AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt;AA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt;AC&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt;BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
 CA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;&lt;br /&gt;
 BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt;&lt;br /&gt;
 AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt;&lt;br /&gt;
 AA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt;&lt;br /&gt;
 AC&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt;&lt;br /&gt;
 BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt;&lt;br /&gt;
 AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Таким образом, поскольку на каждом шаге алгоритма получившиеся строки являлись суффиксами циклических перестановок &amp;lt;tex&amp;gt; $s$ &amp;lt;/tex&amp;gt;, после последнего шага получившиеся строки будут совпадать с циклическими перестановками &amp;lt;tex&amp;gt; $s$ &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Оптимизированный наивный алгоритм===&lt;br /&gt;
&lt;br /&gt;
Наивный алгоритм можно оптимизировать. Заметим, что при каждом проявлении неизвестного столбца выполнялись одни и те же действия. Мы приписывали новый столбец и сортировали имеющиеся данные. На каждом шагу мы к строке, которая находилась на &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;-ом месте приписываем в начало &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; -ый элемент столбца входных данных. Пусть изначально мы знаем каким по порядку является приписанный нами в начало символ (то есть каким по порядку в столбце). И конечно же мы знаем исходя из предыдущего шага какое место занимала наша строка без этого первого символа (&amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; -ое). Тогда несложно заметить, что при выполнении такой операции строка с номером &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; всегда будет перемещаться на позицию с номером &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 {| border=&amp;quot;1&amp;quot;&lt;br /&gt;
  |0||а||&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;||р||9&lt;br /&gt;
  |-&lt;br /&gt;
  |1||а||||д||7&lt;br /&gt;
  |-&lt;br /&gt;
  |2||а|| ||a||0&lt;br /&gt;
  |-&lt;br /&gt;
  |3||а|| ||к||8&lt;br /&gt;
  |-&lt;br /&gt;
  |4||а|| ||р||10&lt;br /&gt;
  |-&lt;br /&gt;
  |5||б|| ||a||1&lt;br /&gt;
  |-&lt;br /&gt;
  |6||б|| ||a||2&lt;br /&gt;
  |-&lt;br /&gt;
  |7||д|| ||a||3&lt;br /&gt;
  |-&lt;br /&gt;
  |8||к|| ||a||4&lt;br /&gt;
  |-&lt;br /&gt;
  |9||р|| ||б||5&lt;br /&gt;
  |-&lt;br /&gt;
  |10||р|| ||б||6&lt;br /&gt;
  |}&lt;br /&gt;
&lt;br /&gt;
Здесь слева отсортированный данный столбец, чтобы мы знали, какое место в лексикографическом порядке занимает приписываемый нами символ среди всех элементов данного нам изначально столбца. Справа - изначально данный столбец и соответствующее ему число. Поскольку в нашем алгоритме новый столбец приписывается в начало, то мы из состояния &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; (левый столбец) переходим в состояние &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; (правый). Для того, чтобы восстановить строку, нам необходимо от последней такой цифры по пути из &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; восстановить строку.&lt;br /&gt;
{|&lt;br /&gt;
 |&lt;br /&gt;
 {| border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |6&lt;br /&gt;
 |→&lt;br /&gt;
 |10&lt;br /&gt;
 |→&lt;br /&gt;
 |4 &lt;br /&gt;
 |→&lt;br /&gt;
 |8&lt;br /&gt;
 |→ &lt;br /&gt;
 |3&lt;br /&gt;
 |→&lt;br /&gt;
 |7&lt;br /&gt;
 |→&lt;br /&gt;
 |1&lt;br /&gt;
 |→&lt;br /&gt;
 |5&lt;br /&gt;
 |→&lt;br /&gt;
 |9&lt;br /&gt;
 |→&lt;br /&gt;
 |0&lt;br /&gt;
 |→&lt;br /&gt;
 |2&lt;br /&gt;
 |-&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |б&lt;br /&gt;
 |&lt;br /&gt;
 |р&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |к&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |д&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |б&lt;br /&gt;
 |&lt;br /&gt;
 |р&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
|}&lt;br /&gt;
====Сложность оптимизированного алгоритма====&lt;br /&gt;
Данный алгоритм работает за &amp;lt;tex&amp;gt;O(N\log{N})&amp;lt;/tex&amp;gt; времени и требует &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt; памяти. Однако, если размер алфавита не очень большой, то для выяснения первого столбца матрицы можно использовать сортировку подсчетом, в этом случае алгоритм работает за &amp;lt;tex&amp;gt;O(N+M)&amp;lt;/tex&amp;gt; действий и требует &amp;lt;tex&amp;gt;O(N+M)&amp;lt;/tex&amp;gt; памяти, где &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; — размер алфавита.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод оптимизированного алгоритма===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; N &amp;lt;/tex&amp;gt; — количество символов во входной строке, &amp;lt;tex&amp;gt; M &amp;lt;/tex&amp;gt; — количество символов в алфавите, &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; — номер исходной строки в матрице перестановок, &amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt; — входящая строка, &amp;lt;tex&amp;gt; count &amp;lt;/tex&amp;gt;  — массив для сортировки подсчетом, &amp;lt;tex&amp;gt; t &amp;lt;/tex&amp;gt; — вектор обратного преобразования, &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; — номер данной нам строки в таблице.&lt;br /&gt;
&lt;br /&gt;
 // Cчитаем частоты символов&lt;br /&gt;
 for i = 0 .. M &lt;br /&gt;
   count[i] = 0&lt;br /&gt;
 for i = 0 .. N &lt;br /&gt;
   count[s[i]]++&lt;br /&gt;
 // Упорядочиваем символы, чтобы получить первый столбец исходной матрицы&lt;br /&gt;
 // count[i] указывает на первую позицию символа i в первом столбце&lt;br /&gt;
 sum = 0&lt;br /&gt;
 for i = 0 .. M&lt;br /&gt;
   sum = sum + count[i]&lt;br /&gt;
   count[i] = sum - count[i]&lt;br /&gt;
 // Cоздаем вектор обратного преобразования&lt;br /&gt;
 for i = 0 .. N&lt;br /&gt;
   t[count[s[i]]] = i&lt;br /&gt;
   count[s[i]]++&lt;br /&gt;
 // И восстанавливаем исходный текст&lt;br /&gt;
 j = t[x]&lt;br /&gt;
 for i = 0 .. N&lt;br /&gt;
   print(s[j])&lt;br /&gt;
   j = t[j]&lt;br /&gt;
&lt;br /&gt;
====Доказательство корректности====&lt;br /&gt;
&lt;br /&gt;
Пусть текст &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; состоит из &amp;lt;tex&amp;gt;N + 1&amp;lt;/tex&amp;gt; символов, занумерованных с нуля: &amp;lt;tex&amp;gt;T[0..N]&amp;lt;/tex&amp;gt;. Буквы &amp;lt;tex&amp;gt;T[i]&amp;lt;/tex&amp;gt; принадлежат некоторому алфавиту &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Лексикографический порядок (строгий) на строках из алфавита &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; будем обозначать &amp;lt;tex&amp;gt;\preceq (\prec)&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt;S_{k}T&amp;lt;/tex&amp;gt; циклический сдвиг текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; символов влево:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt; S_{k}T = T[(j + k) (mod\ N + 1)] &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Существует перестановка &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;\{0, ..., N\}&amp;lt;/tex&amp;gt;, которая удовлетворяет условию: &lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt; S_{p(i)}T \preceq S_{p(i + 1)}T,\ i = 0, ..., N - 1\ \ \textbf{(1)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Преобразование Барроуза-Уилера текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; есть текст &amp;lt;tex&amp;gt;B[0..N] = BW(T)&amp;lt;/tex&amp;gt;, буквы которого заданы соотношением:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt;B[i] = S_{p(i)}T[N]&amp;lt;/tex&amp;gt;, другими словами &amp;lt;tex&amp;gt;B[i] = S_{p(i) - 1}T[0] = T[(p(i) - 1) (mod\ N + 1)] \ \ \textbf{(2)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} перестановка чисел &amp;lt;tex&amp;gt;\{0, ..., N\}&amp;lt;/tex&amp;gt;, удовлетворяющая условию:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt;B_{\sigma(i)} \preceq B_{\sigma(i + 1)}&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N - 1\ \ \textbf{(3)}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
|}&lt;br /&gt;
и в случае равенства &amp;lt;tex&amp;gt;B_{\sigma(i)}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;B_{\sigma(i + 1)}&amp;lt;/tex&amp;gt; выполнено {{---}} &amp;lt;tex&amp;gt;\sigma(i) &amp;lt; \sigma(i + 1)&amp;lt;/tex&amp;gt;. Перестановка однозначно определяется текстом &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; и ее можно посчитать за &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt;, используя сортировку подсчетом. Рассмотрим перестановку &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; как отображение &amp;lt;tex&amp;gt;\sigma : \{0, ..., N\} \to \{0, ..., N\}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;\sigma^{k}&amp;lt;/tex&amp;gt; копмозиция &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; отображений &amp;lt;tex&amp;gt;\sigma^{k} = \sigma^{k - 1} \circ \sigma&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\sigma^{1} = \sigma, \sigma^{0} \equiv i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
&lt;br /&gt;
''При всех &amp;lt;tex&amp;gt;m = 1, ..., N + 1&amp;lt;/tex&amp;gt; верны утверждения,&lt;br /&gt;
:&amp;lt;tex&amp;gt;B_{\sigma(i)}...B_{\sigma^{m}(i)} \preceq B_{\sigma(i + 1)}...B_{\sigma^{m}(i + 1)}&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N - 1\ \ \textbf{(4)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;B_iB_{\sigma(i)}...B_{\sigma^{m - 1}(i)} = S_{p(i) - 1}T[0..m - 1]&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N\ \ \textbf{(5)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
|proof=&lt;br /&gt;
&lt;br /&gt;
Если лексикографически отсортировать буквы последнего столбца и поместить их в первый столбец, то получится таблица&lt;br /&gt;
&lt;br /&gt;
| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Таблица&lt;br /&gt;
|-&lt;br /&gt;
|a||b||c&lt;br /&gt;
|-&lt;br /&gt;
|a||b||c&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
&lt;br /&gt;
''Для восстановления исходного текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из преобразования &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; достаточно знать число &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;, отвечающее условию &amp;lt;tex&amp;gt;p(I) = 0&amp;lt;/tex&amp;gt;, другими словами &amp;lt;tex&amp;gt;S_{p(I)}T = T&amp;lt;/tex&amp;gt;.''&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Алгоритм за линейное время===&lt;br /&gt;
&lt;br /&gt;
Будем обозначать &amp;lt;tex&amp;gt;s^i&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ую циклическую перестановку &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;s^0 = s_0 s_1 \ldots s_{n-1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;$BWT(s)$\;= L&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;L = L_0L_1\ldots L_{n-1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; - номер строки &amp;lt;tex&amp;gt;s^0&amp;lt;/tex&amp;gt; в таблице. Предподсчитаем следующие величины:&lt;br /&gt;
* Для каждого &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt; количество символов на подстроке &amp;lt;tex&amp;gt;L_0 \ldots L_{i-1}&amp;lt;/tex&amp;gt;, равных &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
* Для каждого уникального &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt; количество символов в &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;, лексикографически меньших, чем &amp;lt;tex&amp;gt;L_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пример для &amp;lt;tex&amp;gt;$BWT(s) =$&amp;lt;/tex&amp;gt; &amp;quot;BCABAAA&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
{|border =&amp;quot;1&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;3&amp;quot; | Таблица первого предподсчёта&lt;br /&gt;
|-&lt;br /&gt;
! Позиция || Символ || Результат&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
! 0 || B || 0&lt;br /&gt;
|-&lt;br /&gt;
! 1 || C || 0&lt;br /&gt;
|-&lt;br /&gt;
! 2 || A || 0&lt;br /&gt;
|-&lt;br /&gt;
! 3 || B || 1&lt;br /&gt;
|-&lt;br /&gt;
! 4 || A || 1&lt;br /&gt;
|-&lt;br /&gt;
! 5 || A || 2&lt;br /&gt;
|-&lt;br /&gt;
! 6 || A || 3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|border =&amp;quot;1&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; | Таблица второго предподсчёта&lt;br /&gt;
|-&lt;br /&gt;
! Символ || Количество  &amp;lt;br /&amp;gt; меньших&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
! A || 0&lt;br /&gt;
|-&lt;br /&gt;
! B || 4&lt;br /&gt;
|-&lt;br /&gt;
! C || 6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Для удобства пронумеруем известные нам данные:&lt;br /&gt;
# &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;, последний столбец таблицы перестановок&lt;br /&gt;
# &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;, номер строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt; в таблице перестановок&lt;br /&gt;
# Частота, с которой символ &amp;lt;tex&amp;gt;L_{i}&amp;lt;/tex&amp;gt; встречается в подстроке &amp;lt;tex&amp;gt;L_0\ldots L_{i-1}&amp;lt;/tex&amp;gt;&lt;br /&gt;
# Для каждого уникального символа количество лексикографически меньших символов в &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Символ &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt; находится в строке &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; под номером &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;, так как в таблице строка &amp;lt;tex&amp;gt;s^0&amp;lt;/tex&amp;gt; имела номер &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;. Найдём символ &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Символ &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt; имеет в строке &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; тот же номер, что строка &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt; имела в таблице перестановок: строка &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt; начинается с символа &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt; находится на 1 левее его и из-за циклического сдвига оказывается в последнем столбце. Нам известен символ &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;. Посчитаем, на каком месте в таблице будет стоять строка, начинающаяся с этого символа.&lt;br /&gt;
&lt;br /&gt;
Из 4 известно количество символов, меньших &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;. Все строки, начинающиеся с этих символов, стоят в таблице раньше &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt;. Кроме того, в таблице есть строки, начинающиеся с того же символа, что и &amp;lt;tex&amp;gt;s^{n-1}&amp;lt;/tex&amp;gt;. Из 3 известно, сколько их: если символ, равный &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, встречался в &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; раньше, чем &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, то в таблице строка, начинающаяся с этого символа, тоже стоит раньше строки, начинающейся с &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;, так как префикс строки, оканчивающейся на этот символ, меньше префикса строки, оканчивающейся на &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Тогда сумма этих двух величин является номером символа &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt; в строке &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt;. Зная &amp;lt;tex&amp;gt;s_{n-1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;s_{n-2}&amp;lt;/tex&amp;gt;, аналогично найдём &amp;lt;tex&amp;gt;s_{n-3}\ldots s_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предподсчёт занимает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени, восстановление каждого из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; символов занимает &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; времени. Суммарное время работы алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пример работы для &amp;lt;tex&amp;gt;$BWT(s) = ($&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, 2&amp;lt;tex&amp;gt;)&amp;lt;/tex&amp;gt; (нумерация с 0):&lt;br /&gt;
* &amp;lt;tex&amp;gt;s^0 = .......&amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;s_6=L_2 = A&amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt;s^0=......&amp;lt;/tex&amp;gt;A&lt;br /&gt;
* Суммируем значения из двух таблиц: &amp;lt;tex&amp;gt;0+0=0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_5=L_0=B&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=.....&amp;lt;/tex&amp;gt;BA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;0+4=4&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_4=L_4=A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=....&amp;lt;/tex&amp;gt;ABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;1+0=1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_3=L_1=C&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=...&amp;lt;/tex&amp;gt;CABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;0+6=6&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_2=L_6=A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=..&amp;lt;/tex&amp;gt;ACABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;3+0=3&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_2=L_3=B&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=.&amp;lt;/tex&amp;gt;BACABA&lt;br /&gt;
* Суммируем: &amp;lt;tex&amp;gt;1+4=5&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s_2=L_5=A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;s^0=&amp;lt;/tex&amp;gt;ABACABA&lt;br /&gt;
&lt;br /&gt;
== Дополнительно ==&lt;br /&gt;
&lt;br /&gt;
* bzip2 использует преобразование Барроуза {{---}} Уилера для превращения последовательностей многократно чередующихся символов в строки одинаковых символов, затем применяет преобразование MTF (англ. move-to-front), и в конце кодирование Хаффмана.&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
*[http://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0_%E2%80%94_%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0 Преобразование Барроуза {{---}} Уилера (Википедия)]&lt;br /&gt;
&lt;br /&gt;
*[http://www.cs.karelia.ru/~aborod/inf/2010/schedule.php.ru Преобразование Барроуза {{---}} Уилера (cs.karelia.ru)]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы сжатия ]]&lt;/div&gt;</summary>
		<author><name>Evarand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0-%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0&amp;diff=50143</id>
		<title>Преобразование Барроуза-Уилера</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0-%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0&amp;diff=50143"/>
				<updated>2015-12-06T13:51:36Z</updated>
		
		<summary type="html">&lt;p&gt;Evarand: Доказательство корректности наивного алгоритма&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Определение ==&lt;br /&gt;
&lt;br /&gt;
'''Преобразование Барроуза {{---}} Уилера''' (англ. ''Burrows-Wheeler transform'') {{---}} алгоритм, используемый для предварительной обработки данных перед сжатием, разработанный для улучшения эффективности последующего кодирования. Преобразование Барроуза {{---}} Уилера меняет порядок символов во входной строке таким образом, что повторяющиеся подстроки образуют на выходе идущие подряд последовательности одинаковых символов.&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Преобразование выполняется в три этапа. &lt;br /&gt;
* Составляется таблица всех циклических сдвигов входной строки.&lt;br /&gt;
* Производится лексикографическая (в алфавитном порядке) сортировка строк таблицы.&lt;br /&gt;
* В качестве выходной строки выбирается последний столбец таблицы преобразования и номер строки, совпадающей с исходной.&lt;br /&gt;
&lt;br /&gt;
== Пример работы алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дана исходная строка &amp;lt;tex&amp;gt;$s =$&amp;lt;/tex&amp;gt; &amp;quot;ABACABA&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;4&amp;quot;|Трансформация&lt;br /&gt;
|-&lt;br /&gt;
! Вход || Все&amp;lt;br /&amp;gt;Перестановки || Сортировка&amp;lt;br /&amp;gt;Строк || Выход&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
 BACABAA&lt;br /&gt;
 ACABAAB&lt;br /&gt;
 CABAABA&lt;br /&gt;
 ABAABAC&lt;br /&gt;
 BAABACA&lt;br /&gt;
 AABACAB&lt;br /&gt;
|&lt;br /&gt;
 AABACAB&lt;br /&gt;
 ABAABAC&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
 ACABAAB&lt;br /&gt;
 BAABACA&lt;br /&gt;
 BACABAA&lt;br /&gt;
 CABAABA &lt;br /&gt;
|&lt;br /&gt;
 BCABAAA, 3&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Результат можно записать так: &amp;lt;tex&amp;gt;$BWT(s) = $(&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, 3&amp;lt;tex&amp;gt;)&amp;lt;/tex&amp;gt;, где 3 {{---}} номер исходной строки в отсортированной матрице. Он нужен для обратного преобразования. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следует заметить, что иногда в исходной строке приводится так называемый символ конца строки ''$'', который в преобразовании будет считаться последним (максимальным) символом, тогда сохранение номера исходной строки не требуется.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пусть нам дана исходная строка &amp;lt;tex&amp;gt;$s =$&amp;lt;/tex&amp;gt; &amp;quot;ABACABA$&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;4&amp;quot;|Трансформация&lt;br /&gt;
|-&lt;br /&gt;
! Вход || Все&amp;lt;br /&amp;gt;Перестановки || Сортировка&amp;lt;br /&amp;gt;Строк || Выход&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&lt;br /&gt;
 BACABA$A&lt;br /&gt;
 ACABA$AB&lt;br /&gt;
 CABA$ABA&lt;br /&gt;
 ABA$ABAC&lt;br /&gt;
 BA$ABACA&lt;br /&gt;
 A$ABACAB&lt;br /&gt;
 $ABACABA&lt;br /&gt;
&lt;br /&gt;
|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA$&amp;lt;/font&amp;gt;&lt;br /&gt;
 ABA$ABAC&lt;br /&gt;
 ACABA$AB&lt;br /&gt;
 A$ABACAB&lt;br /&gt;
 BACABA$A&lt;br /&gt;
 BA$ABACA&lt;br /&gt;
 CABA$ABA &lt;br /&gt;
 $ABACABA&lt;br /&gt;
|&lt;br /&gt;
 $CBBAAAA&lt;br /&gt;
|} &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
При аналогичном вышеприведённом преобразовании та строчка в матрице, которая будет заканчиваться на символ конца строки, и будет исходной: (&amp;quot;ABACABA$&amp;quot;). Тогда результат можно записать так: &amp;lt;tex&amp;gt;$BWT(s) =$&amp;lt;/tex&amp;gt; &amp;quot;$CBBAAAA&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Обратное преобразование ==&lt;br /&gt;
&lt;br /&gt;
===Наивный алгоритм===&lt;br /&gt;
&lt;br /&gt;
Пусть нам дано: &amp;lt;tex&amp;gt;$BWT(s) =$(&amp;lt;/tex&amp;gt;&amp;quot;BCABAAA&amp;quot;, 3&amp;lt;tex&amp;gt;)&amp;lt;/tex&amp;gt;. Тогда выпишем в столбик нашу преобразованную последовательность символов &amp;quot;BCABAAA&amp;quot;. Запишем её как последний столбик предыдущей матрицы (при прямом преобразовании Барроуза {{---}} Уилера), при этом все предыдущие столбцы оставляем пустыми. Далее построчно отсортируем матрицу, затем в предыдущий столбец запишем &amp;quot;BCABAAA&amp;quot;. Опять построчно отсортируем матрицу. Продолжая таким образом, можно восстановить полный список всех циклических перестановок строки, которую нам надо найти. Выстроив полный отсортированный список перестановок, выберем строку с номером, который нам был изначально дан. В итоге мы получим искомую строку.&lt;br /&gt;
Алгоритм обратного преобразования описан в таблице ниже:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Обратное преобразование&lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Вход&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot; colspan=&amp;quot;8&amp;quot;|&lt;br /&gt;
 BCABAAA&lt;br /&gt;
|-&lt;br /&gt;
! Добавление 1 || Сортировка 1 || Добавление 2 || Сортировка 2 || Добавление 3 || Сортировка 3 || Добавление 4 &lt;br /&gt;
|-align=&amp;quot;right&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
 B&lt;br /&gt;
 C&lt;br /&gt;
 A&lt;br /&gt;
 B&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
|&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 A&lt;br /&gt;
 B&lt;br /&gt;
 B&lt;br /&gt;
 C&lt;br /&gt;
|&lt;br /&gt;
 BA&lt;br /&gt;
 CA&lt;br /&gt;
 AA&lt;br /&gt;
 BA&lt;br /&gt;
 AB&lt;br /&gt;
 AB&lt;br /&gt;
 AC&lt;br /&gt;
|&lt;br /&gt;
 AA&lt;br /&gt;
 AB&lt;br /&gt;
 AB&lt;br /&gt;
 AC&lt;br /&gt;
 BA&lt;br /&gt;
 BA&lt;br /&gt;
 CA&lt;br /&gt;
|&lt;br /&gt;
 BAA&lt;br /&gt;
 CAB&lt;br /&gt;
 AAB&lt;br /&gt;
 BAC&lt;br /&gt;
 ABA&lt;br /&gt;
 ABA&lt;br /&gt;
 ACA&lt;br /&gt;
|&lt;br /&gt;
 AAB&lt;br /&gt;
 ABA&lt;br /&gt;
 ABA&lt;br /&gt;
 ACA&lt;br /&gt;
 BAA&lt;br /&gt;
 BAC&lt;br /&gt;
 CAB&lt;br /&gt;
|&lt;br /&gt;
 BAAB&lt;br /&gt;
 CABA&lt;br /&gt;
 AABA&lt;br /&gt;
 BACA&lt;br /&gt;
 ABAA&lt;br /&gt;
 ABAC&lt;br /&gt;
 ACAB&lt;br /&gt;
|-&lt;br /&gt;
! Сортировка 4 || Добавление 5 || Сортировка 5 || Добавление 6 || Сортировка 6 || Добавление 7 || Сортировка 7&lt;br /&gt;
&lt;br /&gt;
|-align=&amp;quot;right&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
 AABA&lt;br /&gt;
 ABAA&lt;br /&gt;
 ABAC&lt;br /&gt;
 ACAB&lt;br /&gt;
 BAAB&lt;br /&gt;
 BACA&lt;br /&gt;
 CABA&lt;br /&gt;
|&lt;br /&gt;
 BAABA&lt;br /&gt;
 CABAA&lt;br /&gt;
 AABAC&lt;br /&gt;
 BACAB&lt;br /&gt;
 ABAAB&lt;br /&gt;
 ABACA&lt;br /&gt;
 ACABA&lt;br /&gt;
|&lt;br /&gt;
 AABAC&lt;br /&gt;
 ABAAB&lt;br /&gt;
 ABACA&lt;br /&gt;
 ACABA&lt;br /&gt;
 BAABA&lt;br /&gt;
 BACAB&lt;br /&gt;
 CABAA&lt;br /&gt;
|&lt;br /&gt;
 BAABAC&lt;br /&gt;
 CABAAB&lt;br /&gt;
 AABACA&lt;br /&gt;
 BACABA&lt;br /&gt;
 ABAABA&lt;br /&gt;
 ABACAB&lt;br /&gt;
 ACABAA&lt;br /&gt;
|&lt;br /&gt;
 AABACA&lt;br /&gt;
 ABAABA&lt;br /&gt;
 ABACAB&lt;br /&gt;
 ACABAA&lt;br /&gt;
 BAABAC&lt;br /&gt;
 BACABA&lt;br /&gt;
 CABAAB&lt;br /&gt;
|&lt;br /&gt;
 BAABACA&lt;br /&gt;
 CABAABA&lt;br /&gt;
 AABACAB&lt;br /&gt;
 BACABAA&lt;br /&gt;
 ABAABAC&lt;br /&gt;
 ABACABA&lt;br /&gt;
 ACABAAB&lt;br /&gt;
|&lt;br /&gt;
 AABACAB&lt;br /&gt;
 ABAABAC&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
 ACABAAB&lt;br /&gt;
 BAABACA&lt;br /&gt;
 BACABAA&lt;br /&gt;
 CABAABA&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Результат&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot; colspan=&amp;quot;8&amp;quot;|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ABACABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Следует также заметить, что если нам было бы дано &amp;lt;tex&amp;gt;$BWT(s) = $&amp;lt;/tex&amp;gt; &amp;quot;$CBBAAAA&amp;quot;, то мы также получили бы нашу исходную строку, только с символом конца строки ''$'' на конце: ''ABACABA$''.&lt;br /&gt;
&lt;br /&gt;
Временная сложность данного алгоритма &amp;lt;tex&amp;gt;O(N^3\log{N}) &amp;lt;/tex&amp;gt;, пространственная &amp;lt;tex&amp;gt;O(N^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство корректности===&lt;br /&gt;
&lt;br /&gt;
Пусть дана строка &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;, к которой было применено преобразование BWT. Докажем, что при использовании наивного алгоритма на каждом шаге получающийся набор строк соответствует суффиксам циклических перестановок исходной строки, методом математической индукции.&lt;br /&gt;
* База. Циклически сдвинем все строки исходной таблицы на 1 влево. Тогда в столбце &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; будут находиться символы, добавленные на первом шаге алгоритма, а в столбце &amp;lt;tex&amp;gt;n - 1&amp;lt;/tex&amp;gt; символы, изначально стоявшие в таблице до первого шага алгоритма. Таким образом, полученные на первом шаге алгоритма строки являются суффиксами циклических перестановок строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Предположение. Пусть на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; шаге алгоритма все полученные строки являются суффиксами циклических перестановок строки &amp;lt;tex&amp;gt;$s$&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Переход. Рассмотрим &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ый шаг алгоритма. Все строки отсортированы, поэтому самый левый столбец совпадет с 1 столбцом исходной таблицы. Циклически сдвинем все строки исходной таблицы на &amp;lt;tex&amp;gt;n - k&amp;lt;/tex&amp;gt; символов вправо. Теперь по предположению первые &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; символов справа в каждой строке совпадают у исходной таблицы и у таблицы, полученной в результате работы алгоритма. &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;-ые справа столбцы также совпадают. Добавленный на &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ом шаге столбец также совпадает с &amp;lt;tex&amp;gt;k+1&amp;lt;/tex&amp;gt;-ым справа столбцом сдвинутой исходной таблицы, так как совпадает с последним столбцом исходной таблицы, которая была сдвинута на &amp;lt;tex&amp;gt;n-k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{|border =&amp;quot;1&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;3&amp;quot; | &amp;lt;tex&amp;gt;$k+1$&amp;lt;/tex&amp;gt; шаг алгоритма при &amp;lt;tex&amp;gt;$k=3$&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! Исходная &amp;lt;br /&amp;gt; таблица || Сдвинутая &amp;lt;br /&amp;gt; таблица || Результат &amp;lt;br /&amp;gt; работы &amp;lt;br /&amp;gt; алгоритма&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;CA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt;BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt;AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt;AA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt;AC&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt;BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
 CA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;&lt;br /&gt;
 BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt;&lt;br /&gt;
 AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt;&lt;br /&gt;
 AA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt;&lt;br /&gt;
 AC&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt;&lt;br /&gt;
 BA&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt;&lt;br /&gt;
 AB&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
 &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAA&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;BAC&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;CAB&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;AAB&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;B&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ACA&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;A&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;C&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;ABA&amp;lt;/font&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Таким образом, поскольку на каждом шаге алгоритма получившиеся строки являлись суффиксами циклических перестановок &amp;lt;tex&amp;gt; $s$ &amp;lt;/tex&amp;gt;, после последнего шага получившиеся строки будут совпадать с циклическими перестановками &amp;lt;tex&amp;gt; $s$ &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Оптимизация===&lt;br /&gt;
&lt;br /&gt;
Однако, данный алгоритм можно оптимизировать. Заметим, что при каждом проявлении неизвестного столбца выполнялись одни и те же действия. Мы приписывали новый столбец и сортировали имеющиеся данные. На каждом шагу мы к строке, которая находилась на &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;-ом месте приписываем в начало &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; -ый элемент столбца входных данных. Пусть изначально мы знаем каким по порядку является приписанный нами в начало символ (то есть каким по порядку в столбце). И конечно же мы знаем исходя из предыдущего шага какое место занимала наша строка без этого первого символа (&amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; -ое). Тогда несложно заметить, что при выполнении такой операции строка с номером &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; всегда будет перемещаться на позицию с номером &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 {| border=&amp;quot;1&amp;quot;&lt;br /&gt;
  |0||а||&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;||р||9&lt;br /&gt;
  |-&lt;br /&gt;
  |1||а||||д||7&lt;br /&gt;
  |-&lt;br /&gt;
  |2||а|| ||a||0&lt;br /&gt;
  |-&lt;br /&gt;
  |3||а|| ||к||8&lt;br /&gt;
  |-&lt;br /&gt;
  |4||а|| ||р||10&lt;br /&gt;
  |-&lt;br /&gt;
  |5||б|| ||a||1&lt;br /&gt;
  |-&lt;br /&gt;
  |6||б|| ||a||2&lt;br /&gt;
  |-&lt;br /&gt;
  |7||д|| ||a||3&lt;br /&gt;
  |-&lt;br /&gt;
  |8||к|| ||a||4&lt;br /&gt;
  |-&lt;br /&gt;
  |9||р|| ||б||5&lt;br /&gt;
  |-&lt;br /&gt;
  |10||р|| ||б||6&lt;br /&gt;
  |}&lt;br /&gt;
&lt;br /&gt;
Здесь слева отсортированный данный столбец, чтобы мы знали, какое место в лексикографическом порядке занимает приписываемый нами символ среди всех элементов данного нам изначально столбца. Справа - изначально данный столбец и соответствующее ему число. Поскольку в нашем алгоритме новый столбец приписывается в начало, то мы из состояния &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; (левый столбец) переходим в состояние &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; (правый). Для того, чтобы восстановить строку, нам необходимо от последней такой цифры по пути из &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; восстановить строку.&lt;br /&gt;
{|&lt;br /&gt;
 |&lt;br /&gt;
 {| border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |6&lt;br /&gt;
 |→&lt;br /&gt;
 |10&lt;br /&gt;
 |→&lt;br /&gt;
 |4 &lt;br /&gt;
 |→&lt;br /&gt;
 |8&lt;br /&gt;
 |→ &lt;br /&gt;
 |3&lt;br /&gt;
 |→&lt;br /&gt;
 |7&lt;br /&gt;
 |→&lt;br /&gt;
 |1&lt;br /&gt;
 |→&lt;br /&gt;
 |5&lt;br /&gt;
 |→&lt;br /&gt;
 |9&lt;br /&gt;
 |→&lt;br /&gt;
 |0&lt;br /&gt;
 |→&lt;br /&gt;
 |2&lt;br /&gt;
 |-&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |б&lt;br /&gt;
 |&lt;br /&gt;
 |р&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |к&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |д&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
 |&lt;br /&gt;
 |б&lt;br /&gt;
 |&lt;br /&gt;
 |р&lt;br /&gt;
 |&lt;br /&gt;
 |а&lt;br /&gt;
|}&lt;br /&gt;
===Сложность оптимизированного алгоритма===&lt;br /&gt;
Данный алгоритм работает за &amp;lt;tex&amp;gt;O(N\log{N})&amp;lt;/tex&amp;gt; времени и требует &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt; памяти. Однако, если размер алфавита не очень большой, то для выяснения первого столбца матрицы можно использовать сортировку подсчетом, в этом случае алгоритм работает за &amp;lt;tex&amp;gt;O(N+M)&amp;lt;/tex&amp;gt; действий и требует &amp;lt;tex&amp;gt;O(N+M)&amp;lt;/tex&amp;gt; памяти, где &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; — размер алфавита.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод оптимизированного алгоритма===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; N &amp;lt;/tex&amp;gt; — количество символов во входной строке, &amp;lt;tex&amp;gt; M &amp;lt;/tex&amp;gt; — количество символов в алфавите, &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; — номер исходной строки в матрице перестановок, &amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt; — входящая строка, &amp;lt;tex&amp;gt; count &amp;lt;/tex&amp;gt;  — массив для сортировки подсчетом, &amp;lt;tex&amp;gt; t &amp;lt;/tex&amp;gt; — вектор обратного преобразования, &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; — номер данной нам строки в таблице.&lt;br /&gt;
&lt;br /&gt;
 // Cчитаем частоты символов&lt;br /&gt;
 for i = 0 .. M &lt;br /&gt;
   count[i] = 0&lt;br /&gt;
 for i = 0 .. N &lt;br /&gt;
   count[s[i]]++&lt;br /&gt;
 // Упорядочиваем символы, чтобы получить первый столбец исходной матрицы&lt;br /&gt;
 // count[i] указывает на первую позицию символа i в первом столбце&lt;br /&gt;
 sum = 0&lt;br /&gt;
 for i = 0 .. M&lt;br /&gt;
   sum = sum + count[i]&lt;br /&gt;
   count[i] = sum - count[i]&lt;br /&gt;
 // Cоздаем вектор обратного преобразования&lt;br /&gt;
 for i = 0 .. N&lt;br /&gt;
   t[count[s[i]]] = i&lt;br /&gt;
   count[s[i]]++&lt;br /&gt;
 // И восстанавливаем исходный текст&lt;br /&gt;
 j = t[x]&lt;br /&gt;
 for i = 0 .. N&lt;br /&gt;
   print(s[j])&lt;br /&gt;
   j = t[j]&lt;br /&gt;
&lt;br /&gt;
===Доказательство корректности===&lt;br /&gt;
&lt;br /&gt;
Пусть текст &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; состоит из &amp;lt;tex&amp;gt;N + 1&amp;lt;/tex&amp;gt; символов, занумерованных с нуля: &amp;lt;tex&amp;gt;T[0..N]&amp;lt;/tex&amp;gt;. Буквы &amp;lt;tex&amp;gt;T[i]&amp;lt;/tex&amp;gt; принадлежат некоторому алфавиту &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Лексикографический порядок (строгий) на строках из алфавита &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; будем обозначать &amp;lt;tex&amp;gt;\preceq (\prec)&amp;lt;/tex&amp;gt;. Обозначим через &amp;lt;tex&amp;gt;S_{k}T&amp;lt;/tex&amp;gt; циклический сдвиг текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; символов влево:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt; S_{k}T = T[(j + k) (mod\ N + 1)] &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Существует перестановка &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;\{0, ..., N\}&amp;lt;/tex&amp;gt;, которая удовлетворяет условию: &lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt; S_{p(i)}T \preceq S_{p(i + 1)}T,\ i = 0, ..., N - 1\ \ \textbf{(1)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Преобразование Барроуза-Уилера текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; есть текст &amp;lt;tex&amp;gt;B[0..N] = BW(T)&amp;lt;/tex&amp;gt;, буквы которого заданы соотношением:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt;B[i] = S_{p(i)}T[N]&amp;lt;/tex&amp;gt;, другими словами &amp;lt;tex&amp;gt;B[i] = S_{p(i) - 1}T[0] = T[(p(i) - 1) (mod\ N + 1)] \ \ \textbf{(2)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; {{---}} перестановка чисел &amp;lt;tex&amp;gt;\{0, ..., N\}&amp;lt;/tex&amp;gt;, удовлетворяющая условию:&lt;br /&gt;
:{|&lt;br /&gt;
&amp;lt;tex&amp;gt;B_{\sigma(i)} \preceq B_{\sigma(i + 1)}&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N - 1\ \ \textbf{(3)}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
|}&lt;br /&gt;
и в случае равенства &amp;lt;tex&amp;gt;B_{\sigma(i)}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;B_{\sigma(i + 1)}&amp;lt;/tex&amp;gt; выполнено {{---}} &amp;lt;tex&amp;gt;\sigma(i) &amp;lt; \sigma(i + 1)&amp;lt;/tex&amp;gt;. Перестановка однозначно определяется текстом &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; и ее можно посчитать за &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt;, используя сортировку подсчетом. Рассмотрим перестановку &amp;lt;tex&amp;gt;\sigma&amp;lt;/tex&amp;gt; как отображение &amp;lt;tex&amp;gt;\sigma : \{0, ..., N\} \to \{0, ..., N\}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;\sigma^{k}&amp;lt;/tex&amp;gt; копмозиция &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; отображений &amp;lt;tex&amp;gt;\sigma^{k} = \sigma^{k - 1} \circ \sigma&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\sigma^{1} = \sigma, \sigma^{0} \equiv i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
&lt;br /&gt;
''При всех &amp;lt;tex&amp;gt;m = 1, ..., N + 1&amp;lt;/tex&amp;gt; верны утверждения,&lt;br /&gt;
:&amp;lt;tex&amp;gt;B_{\sigma(i)}...B_{\sigma^{m}(i)} \preceq B_{\sigma(i + 1)}...B_{\sigma^{m}(i + 1)}&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N - 1\ \ \textbf{(4)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;B_iB_{\sigma(i)}...B_{\sigma^{m - 1}(i)} = S_{p(i) - 1}T[0..m - 1]&amp;lt;/tex&amp;gt;, при &amp;lt;tex&amp;gt;i = 0, ..., N\ \ \textbf{(5)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
|proof=&lt;br /&gt;
&lt;br /&gt;
Если лексикографически отсортировать буквы последнего столбца и поместить их в первый столбец, то получится таблица&lt;br /&gt;
&lt;br /&gt;
| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Таблица&lt;br /&gt;
|-&lt;br /&gt;
|a||b||c&lt;br /&gt;
|-&lt;br /&gt;
|a||b||c&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
&lt;br /&gt;
''Для восстановления исходного текста &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из преобразования &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; достаточно знать число &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;, отвечающее условию &amp;lt;tex&amp;gt;p(I) = 0&amp;lt;/tex&amp;gt;, другими словами &amp;lt;tex&amp;gt;S_{p(I)}T = T&amp;lt;/tex&amp;gt;.''&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Дополнительно ==&lt;br /&gt;
&lt;br /&gt;
* bzip2 использует преобразование Барроуза {{---}} Уилера для превращения последовательностей многократно чередующихся символов в строки одинаковых символов, затем применяет преобразование MTF (англ. move-to-front), и в конце кодирование Хаффмана.&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
*[http://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%B0%D1%80%D1%80%D0%BE%D1%83%D0%B7%D0%B0_%E2%80%94_%D0%A3%D0%B8%D0%BB%D0%B5%D1%80%D0%B0 Преобразование Барроуза {{---}} Уилера (Википедия)]&lt;br /&gt;
&lt;br /&gt;
*[http://www.cs.karelia.ru/~aborod/inf/2010/schedule.php.ru Преобразование Барроуза {{---}} Уилера (cs.karelia.ru)]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы сжатия ]]&lt;/div&gt;</summary>
		<author><name>Evarand</name></author>	</entry>

	</feed>