<?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=Gamezovladislav</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=Gamezovladislav"/>
		<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/Gamezovladislav"/>
		<updated>2026-06-11T14:19:03Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<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_MTF&amp;diff=44631</id>
		<title>Преобразование MTF</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_MTF&amp;diff=44631"/>
				<updated>2015-01-15T19:36:35Z</updated>
		
		<summary type="html">&lt;p&gt;Gamezovladislav: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Преобразование MTF''' (англ. ''move-to-front'', движение к началу) {{---}} алгоритм кодирования, используемый для предварительной обработки данных (обычно потока байтов) перед сжатием, разработанный для улучшения эффективности последующего кодирования.&lt;br /&gt;
}}&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Изначально каждое возможное значение байта записывается в список (алфавит), в ячейку с номером, равным значению байта, т.е. &amp;lt;tex&amp;gt;(0, 1, 2, 3, \dots, 255)&amp;lt;/tex&amp;gt;. В процессе обработки данных этот список изменяется. По мере поступления очередного символа на выход подается номер элемента, содержащего его значение. После чего этот символ перемещается в начало списка, смещая остальные элементы вправо.&lt;br /&gt;
&lt;br /&gt;
Современные алгоритмы (например, bzip2&amp;lt;ref&amp;gt;[http://ru.wikipedia.org/wiki/Bzip2 {{---}} bzip2]&amp;lt;/ref&amp;gt;) перед алгоритмом MTF используют [[преобразование Барроуза-Уиллера|алгоритм BWT]], поэтому в качестве примера рассмотрим строку &amp;lt;tex&amp;gt;S = BCABAAA&amp;lt;/tex&amp;gt;, полученную из строки ''&amp;quot;ABACABA&amp;quot;'' в результате [[Преобразование Барроуза-Уиллера|преобразования Барроуза-Уиллера]]. Первый символ строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; 'B' является вторым элементом алфавита ''&amp;quot;ABC&amp;quot;'', поэтому на вывод подаётся &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. После перемещения 'B' в начало алфавита тот принимает вид ''&amp;quot;BAC&amp;quot;''. Дальнейшая работа алгоритма показана в таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Список || Вывод&lt;br /&gt;
|-&lt;br /&gt;
| B || A'''B'''C || 1&lt;br /&gt;
|-&lt;br /&gt;
| C || BA'''C''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| A || CB'''A''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| B || AC'''B''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| A || B'''A'''C || 1&lt;br /&gt;
|-&lt;br /&gt;
| A || '''A'''BC || 0&lt;br /&gt;
|-&lt;br /&gt;
| A || '''A'''BC || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Таким образом, результат работы алгоритма: &amp;lt;tex&amp;gt;MTF(S) = 1222100&amp;lt;/tex&amp;gt;.  &lt;br /&gt;
&lt;br /&gt;
Вот примерная реализация этого алгоритма. Здесь массив &amp;lt;tex&amp;gt;\mathtt{alphabet}&amp;lt;/tex&amp;gt; хранит количество символов перед символом &amp;lt;tex&amp;gt;S[i]&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; {{---}} длина строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''list&amp;lt;int&amp;gt;''' mtf(N):&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' result(N)&lt;br /&gt;
    '''for''' i = 1 '''to''' N&lt;br /&gt;
       result.append(alphabet[S[i]])&lt;br /&gt;
       помещаем символ S[i] в начало алфавита&lt;br /&gt;
    '''return''' result&lt;br /&gt;
&amp;lt;/code&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Данный алгоритм работает за &amp;lt;tex&amp;gt;O(N \cdot M)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; {{---}} размер алфавита, &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; {{---}} длина строки, что не очень быстро. Этот алгоритм можно реализовать за &amp;lt;tex&amp;gt;O(N\log M)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма за O(N logM) ==&lt;br /&gt;
&lt;br /&gt;
Для решения будем использовать [[Декартово_дерево | декартово дерево]].&lt;br /&gt;
&lt;br /&gt;
Пусть дан алфавит размером &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; и строка &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; длиной &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt;. Запомним для каждого символа алфавита свой ключ. Изначально &amp;lt;tex&amp;gt;\mathtt{keys}['a'] = 0&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\mathtt{keys}['b'] = 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\dots&amp;lt;/tex&amp;gt; , &amp;lt;tex&amp;gt;\mathtt{keys}['z'] = M-1&amp;lt;/tex&amp;gt;. Соединим все вершины в дерево по ключу. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''list&amp;lt;int&amp;gt;''' mtf(N):&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' result(N)&lt;br /&gt;
    minkey = 0&lt;br /&gt;
    '''for''' i = 0 '''to''' N &lt;br /&gt;
       result.append(findanswer(S[i])) &amp;lt;font color=darkgreen&amp;gt;       //Считаем ответ&amp;lt;/font color=darkgreen&amp;gt;        &lt;br /&gt;
       cur = find(keys[S[i]])&amp;lt;font color=darkgreen&amp;gt;                 //Находим вершину в дереве &amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
       split(cur.key)      &amp;lt;font color=darkgreen&amp;gt;                   //Вырезаем вершину из дерева&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
       min_key--           &amp;lt;font color=darkgreen&amp;gt;                   //Уменьшаем минимально-возможный ключ&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
       cur.key = minkey    &amp;lt;font color=darkgreen&amp;gt;                   //Ставим ключ в найденной вершине на минимальный&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
       merge(cur, tree)        &amp;lt;font color=darkgreen&amp;gt;               //Объединяем нашу вершину и дерево по ключу&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
    '''return''' result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция &amp;lt;tex&amp;gt;\mathtt{findanswer}&amp;lt;/tex&amp;gt; считает ответ так: если при спуске из вершины дерева мы должны идти вправо, то прибавляем к ответу количество вершин левого поддерева + 1, иначе ничего не добавляем к ответу.&lt;br /&gt;
&lt;br /&gt;
Функции &amp;lt;tex&amp;gt;\mathtt{split}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathtt{merge}&amp;lt;/tex&amp;gt; {{---}} стандартные функции для [[Декартово_дерево|декартова дерева]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\mathtt{minkey}&amp;lt;/tex&amp;gt; {{---}} число, которое меньше любого ключа дерева.&lt;br /&gt;
&lt;br /&gt;
== Обратное преобразование ==&lt;br /&gt;
&lt;br /&gt;
Пусть даны строка &amp;lt;tex&amp;gt;S = 1222100&amp;lt;/tex&amp;gt; и исходный алфавит ''&amp;quot;ABC&amp;quot;''. Символ с номером &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; в алфавите {{---}} это 'B'. На вывод подаётся 'B', и этот символ перемещается в начало алфавита. Символ с номером &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; в алфавите {{---}} это 'A', поэтому 'A' подается на вывод и перемещается в начало алфавита. Дальнейшее преобразование происходит аналогично.&lt;br /&gt;
&lt;br /&gt;
{| class =&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Список || Вывод&lt;br /&gt;
|-&lt;br /&gt;
| 1 || A'''B'''C || B&lt;br /&gt;
|-&lt;br /&gt;
| 2 || BA'''C''' || C&lt;br /&gt;
|-&lt;br /&gt;
| 2 || CB'''A''' || A&lt;br /&gt;
|-&lt;br /&gt;
| 2 || AC'''B''' || B&lt;br /&gt;
|-&lt;br /&gt;
| 1 || B'''A'''C || A&lt;br /&gt;
|-&lt;br /&gt;
| 0 || '''A'''BC || A&lt;br /&gt;
|-&lt;br /&gt;
| 0 || '''A'''BC || A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Значит, исходная строка &amp;lt;tex&amp;gt;MTF^{-1}(S) = BCABAAA&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
&lt;br /&gt;
Этот метод позволяет легко преобразовать данные, насыщенные длинными повторами разных символов в блок данных, самыми частыми символами которого будут нули. Без MTF нас подстерегают разного рода трудности в решении проблемы адаптации к данным, поскольку в разных местах данных, полученных на выходе [[Преобразование Барроуза-Уиллера|BWT-преобразования]], разные символы являются преобладающими. Зачастую мы встречаемся с последовательностями типа &amp;quot;bbbbbcccccdddddaaaaa&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Попробуем сжать эту последовательность при помощи, например, [[Алгоритм Хаффмана|метода Хаффмана]]. Вероятности всех четырех символов в данном примере равны &amp;lt;tex&amp;gt;1/4&amp;lt;/tex&amp;gt;. Легко посчитать, что в результате кодирования мы получим последовательность длиной &amp;lt;tex&amp;gt;20\cdot2 = 40&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Теперь проделаем то же самое со строкой, подвергнутой MTF-преобразованию (предположим, начальный алфавит выглядит как ''&amp;quot;abcd&amp;quot;''). &lt;br /&gt;
&lt;br /&gt;
''&amp;quot;bbbbbcccccdddddaaaaa&amp;quot;'' {{---}} исходная строка&lt;br /&gt;
&lt;br /&gt;
''&amp;quot;10000200003000030000&amp;quot;'' {{---}} строка после MTF &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Частота || Вероятность || Код Хаффмана&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 16 || 4/5 || 0&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 2 || 1/10 || 10&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 1 || 1/20 || 110&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 1 || 1/20 || 111&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
В результате сжатия получаем последовательность длиной &amp;lt;tex&amp;gt;16\cdot1 + 2\cdot2 + 3\cdot2 = 26&amp;lt;/tex&amp;gt; бит. Стоит заметить, что выигрыш от применения [[Арифметическое кодирование|арифметического кодирования]] для данного примера будет еще значительней.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
&lt;br /&gt;
* [[Преобразование_Барроуза-Уиллера]]&lt;br /&gt;
* [[Алгоритм_LZW]]&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;
# [http://compression.ru/arctest/descript/bwt-faq.htm Burrows Wheeler Transform FAQ]&lt;br /&gt;
# [http://ru.wikipedia.org/wiki/Move-To-Front Move-To-Front (Википедия)]&lt;br /&gt;
#  Ryabko, B. Ya. ''Data compression by means of a «book stack»'', Problems of Information Transmission, 1980, v. 16: (4), pp.&amp;amp;nbsp;265–269.&lt;br /&gt;
# Ryabko, B. Ya.; Horspool, R. Nigel; Cormack, Gordon V. Comments to: ''«A locally adaptive data compression scheme»'' by J. L. Bentley, D. D. Sleator, R. E. Tarjan and V. K. Wei. Comm. ACM 30 (1987), no. 9, 792—794.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы сжатия ]]&lt;/div&gt;</summary>
		<author><name>Gamezovladislav</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_MTF&amp;diff=44605</id>
		<title>Преобразование MTF</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_MTF&amp;diff=44605"/>
				<updated>2015-01-15T17:14:16Z</updated>
		
		<summary type="html">&lt;p&gt;Gamezovladislav: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Преобразование MTF''' (англ. ''move-to-front'', движение к началу) {{---}} алгоритм кодирования, используемый для предварительной обработки данных (обычно потока байтов) перед сжатием, разработанный для улучшения эффективности последующего кодирования.&lt;br /&gt;
}}&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Изначально каждое возможное значение байта записывается в список (алфавит), в ячейку с номером, равным значению байта, т.е. &amp;lt;tex&amp;gt;(0, 1, 2, 3, \dots, 255)&amp;lt;/tex&amp;gt;. В процессе обработки данных этот список изменяется. По мере поступления очередного символа на выход подается номер элемента, содержащего его значение. После чего этот символ перемещается в начало списка, смещая остальные элементы вправо.&lt;br /&gt;
&lt;br /&gt;
Современные алгоритмы (например, bzip2&amp;lt;ref&amp;gt;[http://ru.wikipedia.org/wiki/Bzip2 {{---}} bzip2]&amp;lt;/ref&amp;gt;) перед алгоритмом MTF используют [[преобразование Барроуза-Уиллера|алгоритм BWT]], поэтому в качестве примера рассмотрим строку &amp;lt;tex&amp;gt;S = BCABAAA&amp;lt;/tex&amp;gt;, полученную из строки ''&amp;quot;ABACABA&amp;quot;'' в результате [[Преобразование Барроуза-Уиллера|преобразования Барроуза-Уиллера]]. Первый символ строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; 'B' является вторым элементом алфавита ''&amp;quot;ABC&amp;quot;'', поэтому на вывод подаётся &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. После перемещения 'B' в начало алфавита тот принимает вид ''&amp;quot;BAC&amp;quot;''. Дальнейшая работа алгоритма показана в таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Список || Вывод&lt;br /&gt;
|-&lt;br /&gt;
| B || A'''B'''C || 1&lt;br /&gt;
|-&lt;br /&gt;
| C || BA'''C''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| A || CB'''A''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| B || AC'''B''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| A || B'''A'''C || 1&lt;br /&gt;
|-&lt;br /&gt;
| A || '''A'''BC || 0&lt;br /&gt;
|-&lt;br /&gt;
| A || '''A'''BC || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Таким образом, результат работы алгоритма: &amp;lt;tex&amp;gt;MTF(S) = 1222100&amp;lt;/tex&amp;gt;.  &lt;br /&gt;
&lt;br /&gt;
Вот примерная реализация этого алгоритма. Здесь массив &amp;lt;tex&amp;gt;\mathtt{alphabet}&amp;lt;/tex&amp;gt; хранит количество символов перед символом &amp;lt;tex&amp;gt;S[i]&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; {{---}} длина строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''list&amp;lt;int&amp;gt;''' mtf(N):&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' result(N)&lt;br /&gt;
    '''for''' i = 1 '''to''' N&lt;br /&gt;
       result.append(alphabet[S[i]])&lt;br /&gt;
       помещаем символ S[i] в начало алфавита&lt;br /&gt;
    '''return''' result&lt;br /&gt;
&amp;lt;/code&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Данный алгоритм работает за &amp;lt;tex&amp;gt;O(N \cdot M)&amp;lt;/tex&amp;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;O(N\log(N+M))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма за O(N log(N+M)) ==&lt;br /&gt;
&lt;br /&gt;
Пусть дан алфавит размером &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; и строка &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; длиной &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt;. Заведем массив &amp;lt;tex&amp;gt;\mathtt{used}[1..N+M]&amp;lt;/tex&amp;gt; и последние &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; ячеек заполним единицами. Запомним для каждого символа алфавита позицию в нашем массиве. Например, &amp;lt;tex&amp;gt;\mathtt{alphabet}['a'] = N+1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\mathtt{alphabet}['b'] = N+2&amp;lt;/tex&amp;gt;, ... , &amp;lt;tex&amp;gt;\mathtt{alphabet}['z'] = N+M&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
При обработке &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-го символа посчитаем и выпишем сумму на отрезке &amp;lt;tex&amp;gt;[1, \mathtt{alphabet}[S[i]] - 1]&amp;lt;/tex&amp;gt;, поменяем значения ячеек &amp;lt;tex&amp;gt;\mathtt{used}[N-i+1]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathtt{used}[\mathtt{alphabet}[S[i]]]&amp;lt;/tex&amp;gt; местами, также стоит поменять значение в ячейке &amp;lt;tex&amp;gt;\mathtt{alphabet}[S[i]]&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;N-i+1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''list&amp;lt;int&amp;gt;''' mtf(N):&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' result(N)&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' used(N+M)&lt;br /&gt;
    '''for''' i = 1 '''to''' M                                      &amp;lt;font color=darkgreen&amp;gt;//Заполняем последние M ячеек единицами&amp;lt;/font color=darkgreen&amp;gt; &lt;br /&gt;
       used[i+N] = 1&lt;br /&gt;
    '''for''' i = 1 '''to''' N&lt;br /&gt;
       result.append(sum(1, alphabet[S[i]] - 1))        &amp;lt;font color=darkgreen&amp;gt;//Запоминаем ответ&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
       swap(used[N-i+1], used[alphabet[S[i]]])          &amp;lt;font color=darkgreen&amp;gt;//Меняем значения&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
       alphabet[S[i]] = N-i+1                           &amp;lt;font color=darkgreen&amp;gt;//Изменяем позицию символа в массиве&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
    '''return''' result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функцию &amp;lt;tex&amp;gt;\mathtt{sum}&amp;lt;/tex&amp;gt; можно реализовывать по-разному.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' sum(left, right)&lt;br /&gt;
    result = 0&lt;br /&gt;
    '''for''' i = left '''to''' right&lt;br /&gt;
       result = result + used[i]&lt;br /&gt;
    '''return''' result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Такая реализация работает за &amp;lt;tex&amp;gt;O(right-left)&amp;lt;/tex&amp;gt;, общая сложность алгоритма равна &amp;lt;tex&amp;gt;O(N \cdot M)&amp;lt;/tex&amp;gt; Но можно находить сумму на отрезке при помощи [[Дерево_отрезков._Построение | дерева отрезков]], что сократит время работы до &amp;lt;tex&amp;gt;O(\log(right-left))&amp;lt;/tex&amp;gt;. Итого, общая сложность будет равна &amp;lt;tex&amp;gt;O(N\log(N+M))&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
== Обратное преобразование ==&lt;br /&gt;
&lt;br /&gt;
Пусть даны строка &amp;lt;tex&amp;gt;S = 1222100&amp;lt;/tex&amp;gt; и исходный алфавит ''&amp;quot;ABC&amp;quot;''. Символ с номером &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; в алфавите {{---}} это 'B'. На вывод подаётся 'B', и этот символ перемещается в начало алфавита. Символ с номером &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; в алфавите {{---}} это 'A', поэтому 'A' подается на вывод и перемещается в начало алфавита. Дальнейшее преобразование происходит аналогично.&lt;br /&gt;
&lt;br /&gt;
{| class =&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Список || Вывод&lt;br /&gt;
|-&lt;br /&gt;
| 1 || A'''B'''C || B&lt;br /&gt;
|-&lt;br /&gt;
| 2 || BA'''C''' || C&lt;br /&gt;
|-&lt;br /&gt;
| 2 || CB'''A''' || A&lt;br /&gt;
|-&lt;br /&gt;
| 2 || AC'''B''' || B&lt;br /&gt;
|-&lt;br /&gt;
| 1 || B'''A'''C || A&lt;br /&gt;
|-&lt;br /&gt;
| 0 || '''A'''BC || A&lt;br /&gt;
|-&lt;br /&gt;
| 0 || '''A'''BC || A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Значит, исходная строка &amp;lt;tex&amp;gt;MTF^{-1}(S) = BCABAAA&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
&lt;br /&gt;
Этот метод позволяет легко преобразовать данные, насыщенные длинными повторами разных символов в блок данных, самыми частыми символами которого будут нули. Без MTF нас подстерегают разного рода трудности в решении проблемы адаптации к данным, поскольку в разных местах данных, полученных на выходе [[Преобразование Барроуза-Уиллера|BWT-преобразования]], разные символы являются преобладающими. Зачастую мы встречаемся с последовательностями типа &amp;quot;bbbbbcccccdddddaaaaa&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Попробуем сжать эту последовательность при помощи, например, [[Алгоритм Хаффмана|метода Хаффмана]]. Вероятности всех четырех символов в данном примере равны &amp;lt;tex&amp;gt;1/4&amp;lt;/tex&amp;gt;. Легко посчитать, что в результате кодирования мы получим последовательность длиной &amp;lt;tex&amp;gt;20\cdot2 = 40&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Теперь проделаем то же самое со строкой, подвергнутой MTF-преобразованию (предположим, начальный алфавит выглядит как ''&amp;quot;abcd&amp;quot;''). &lt;br /&gt;
&lt;br /&gt;
''&amp;quot;bbbbbcccccdddddaaaaa&amp;quot;'' {{---}} исходная строка&lt;br /&gt;
&lt;br /&gt;
''&amp;quot;10000200003000030000&amp;quot;'' {{---}} строка после MTF &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Частота || Вероятность || Код Хаффмана&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 16 || 4/5 || 0&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 2 || 1/10 || 10&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 1 || 1/20 || 110&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 1 || 1/20 || 111&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
В результате сжатия получаем последовательность длиной &amp;lt;tex&amp;gt;16\cdot1 + 2\cdot2 + 3\cdot2 = 26&amp;lt;/tex&amp;gt; бит. Стоит заметить, что выигрыш от применения [[Арифметическое кодирование|арифметического кодирования]] для данного примера будет еще значительней.&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;
# [http://compression.ru/arctest/descript/bwt-faq.htm Burrows Wheeler Transform FAQ]&lt;br /&gt;
# [http://ru.wikipedia.org/wiki/Move-To-Front Move-To-Front (Википедия)]&lt;br /&gt;
#  Ryabko, B. Ya. ''Data compression by means of a «book stack»'', Problems of Information Transmission, 1980, v. 16: (4), pp.&amp;amp;nbsp;265–269.&lt;br /&gt;
# Ryabko, B. Ya.; Horspool, R. Nigel; Cormack, Gordon V. Comments to: ''«A locally adaptive data compression scheme»'' by J. L. Bentley, D. D. Sleator, R. E. Tarjan and V. K. Wei. Comm. ACM 30 (1987), no. 9, 792—794.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы сжатия ]]&lt;/div&gt;</summary>
		<author><name>Gamezovladislav</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_MTF&amp;diff=44599</id>
		<title>Преобразование MTF</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_MTF&amp;diff=44599"/>
				<updated>2015-01-15T16:59:45Z</updated>
		
		<summary type="html">&lt;p&gt;Gamezovladislav: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Преобразование MTF''' (англ. ''move-to-front'', движение к началу) {{---}} алгоритм кодирования, используемый для предварительной обработки данных (обычно потока байтов) перед сжатием, разработанный для улучшения эффективности последующего кодирования.&lt;br /&gt;
}}&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Изначально каждое возможное значение байта записывается в список (алфавит), в ячейку с номером, равным значению байта, т.е. &amp;lt;tex&amp;gt;(0, 1, 2, 3, \dots, 255)&amp;lt;/tex&amp;gt;. В процессе обработки данных этот список изменяется. По мере поступления очередного символа на выход подается номер элемента, содержащего его значение. После чего этот символ перемещается в начало списка, смещая остальные элементы вправо.&lt;br /&gt;
&lt;br /&gt;
Современные алгоритмы (например, bzip2&amp;lt;ref&amp;gt;[http://ru.wikipedia.org/wiki/Bzip2 {{---}} bzip2]&amp;lt;/ref&amp;gt;) перед алгоритмом MTF используют [[преобразование Барроуза-Уиллера|алгоритм BWT]], поэтому в качестве примера рассмотрим строку &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;''&amp;quot;BCABAAA&amp;quot;'', полученную из строки ''&amp;quot;ABACABA&amp;quot;'' в результате [[Преобразование Барроуза-Уиллера|преобразования Барроуза-Уиллера]]. Первый символ строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; 'B' является вторым элементом алфавита ''&amp;quot;ABC&amp;quot;'', поэтому на вывод подаётся &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. После перемещения 'B' в начало алфавита тот принимает вид ''&amp;quot;BAC&amp;quot;''. Дальнейшая работа алгоритма показана в таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Список || Вывод&lt;br /&gt;
|-&lt;br /&gt;
| B || A'''B'''C || 1&lt;br /&gt;
|-&lt;br /&gt;
| C || BA'''C''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| A || CB'''A''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| B || AC'''B''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| A || B'''A'''C || 1&lt;br /&gt;
|-&lt;br /&gt;
| A || '''A'''BC || 0&lt;br /&gt;
|-&lt;br /&gt;
| A || '''A'''BC || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Таким образом, результат работы алгоритма: &amp;lt;tex&amp;gt;MTF(S) = &amp;lt;/tex&amp;gt; ''&amp;quot;1222100&amp;quot;''.  &lt;br /&gt;
&lt;br /&gt;
Вот примерная реализация этого алгоритма. Здесь массив &amp;lt;tex&amp;gt;\mathtt{alphabet}&amp;lt;/tex&amp;gt; хранит количество символов перед символом &amp;lt;tex&amp;gt;S[i]&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; {{---}} длина строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''list&amp;lt;int&amp;gt;''' mtf(N):&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' result(N)&lt;br /&gt;
    '''for''' i = 1 '''to''' N&lt;br /&gt;
       result.append(alphabet[S[i]])&lt;br /&gt;
       помещаем символ S[i] в начало алфавита&lt;br /&gt;
    '''return''' result&lt;br /&gt;
&amp;lt;/code&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Данный алгоритм работает за &amp;lt;tex&amp;gt;O(N \cdot M)&amp;lt;/tex&amp;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;O(N\log(N+M))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма за O(N log(N+M)) ==&lt;br /&gt;
&lt;br /&gt;
Пусть дан алфавит размером &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; и строка &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; длиной &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt;. Заведем массив &amp;lt;tex&amp;gt;\mathtt{used}[1..N+M]&amp;lt;/tex&amp;gt; и последние &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; ячеек заполним единицами. Запомним для каждого символа алфавита позицию в нашем массиве. Например, &amp;lt;tex&amp;gt;\mathtt{alphabet}['a'] = N+1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\mathtt{alphabet}['b'] = N+2&amp;lt;/tex&amp;gt;, ... , &amp;lt;tex&amp;gt;\mathtt{alphabet}['z'] = N+M&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
При обработке &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-го символа посчитаем и выпишем сумму на отрезке &amp;lt;tex&amp;gt;[1, \mathtt{alphabet}[S[i]] - 1]&amp;lt;/tex&amp;gt;, поменяем значения ячеек &amp;lt;tex&amp;gt;\mathtt{used}[N-i+1]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathtt{used}[\mathtt{alphabet}[S[i]]]&amp;lt;/tex&amp;gt; местами, также стоит поменять значение в ячейке &amp;lt;tex&amp;gt;\mathtt{alphabet}[S[i]]&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;N-i+1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''list&amp;lt;int&amp;gt;''' mtf(N):&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' result(N)&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' used(N+M)&lt;br /&gt;
    '''for''' i = 1 '''to''' M                                      &amp;lt;font color=darkgreen&amp;gt;//Заполняем последние M ячеек единицами&amp;lt;/font color=darkgreen&amp;gt; &lt;br /&gt;
       used[i+N] = 1&lt;br /&gt;
    '''for''' i = 1 '''to''' N&lt;br /&gt;
       result.append(sum(1, alphabet[S[i]] - 1))        &amp;lt;font color=darkgreen&amp;gt;//Запоминаем ответ&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
       swap(used[N-i+1], used[alphabet[S[i]]])          &amp;lt;font color=darkgreen&amp;gt;//Меняем значения&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
       alphabet[S[i]] = N-i+1                           &amp;lt;font color=darkgreen&amp;gt;//Изменяем позицию символа в массиве&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
    '''return''' result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функцию &amp;lt;tex&amp;gt;\mathtt{sum}&amp;lt;/tex&amp;gt; можно реализовывать по-разному.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' sum(left, right)&lt;br /&gt;
    result = 0&lt;br /&gt;
    '''for''' i = left '''to''' right&lt;br /&gt;
       result = result + used[i]&lt;br /&gt;
    '''return''' result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Такая реализация работает за &amp;lt;tex&amp;gt;O(right-left)&amp;lt;/tex&amp;gt;, общая сложность алгоритма равна &amp;lt;tex&amp;gt;O(N \cdot M)&amp;lt;/tex&amp;gt; Но можно находить сумму на отрезке при помощи [[Дерево_отрезков._Построение | дерева отрезков]], что сократит время работы до &amp;lt;tex&amp;gt;O(\log(right-left))&amp;lt;/tex&amp;gt;. Итого, общая сложность будет равна &amp;lt;tex&amp;gt;O(N\log(N+M))&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;''&amp;quot;1222100&amp;quot;'' и исходный алфавит ''&amp;quot;ABC&amp;quot;''. Символ с номером &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; в алфавите {{---}} это 'B'. На вывод подаётся 'B', и этот символ перемещается в начало алфавита. Символ с номером &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; в алфавите {{---}} это 'A', поэтому 'A' подается на вывод и перемещается в начало алфавита. Дальнейшее преобразование происходит аналогично.&lt;br /&gt;
&lt;br /&gt;
{| class =&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Список || Вывод&lt;br /&gt;
|-&lt;br /&gt;
| 1 || A'''B'''C || B&lt;br /&gt;
|-&lt;br /&gt;
| 2 || BA'''C''' || C&lt;br /&gt;
|-&lt;br /&gt;
| 2 || CB'''A''' || A&lt;br /&gt;
|-&lt;br /&gt;
| 2 || AC'''B''' || B&lt;br /&gt;
|-&lt;br /&gt;
| 1 || B'''A'''C || A&lt;br /&gt;
|-&lt;br /&gt;
| 0 || '''A'''BC || A&lt;br /&gt;
|-&lt;br /&gt;
| 0 || '''A'''BC || A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Значит, исходная строка &amp;lt;tex&amp;gt;MTF^{-1}(S) = &amp;lt;/tex&amp;gt;''&amp;quot;BCABAAA&amp;quot;''.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
&lt;br /&gt;
Этот метод позволяет легко преобразовать данные, насыщенные длинными повторами разных символов в блок данных, самыми частыми символами которого будут нули. Без MTF нас подстерегают разного рода трудности в решении проблемы адаптации к данным, поскольку в разных местах данных, полученных на выходе [[Преобразование Барроуза-Уиллера|BWT-преобразования]], разные символы являются преобладающими. Зачастую мы встречаемся с последовательностями типа &amp;quot;bbbbbcccccdddddaaaaa&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Попробуем сжать эту последовательность при помощи, например, [[Алгоритм Хаффмана|метода Хаффмана]]. Вероятности всех четырех символов в данном примере равны &amp;lt;tex&amp;gt;1/4&amp;lt;/tex&amp;gt;. Легко посчитать, что в результате кодирования мы получим последовательность длиной &amp;lt;tex&amp;gt;20\cdot2 = 40&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Теперь проделаем то же самое со строкой, подвергнутой MTF-преобразованию (предположим, начальный алфавит выглядит как ''&amp;quot;abcd&amp;quot;''). &lt;br /&gt;
&lt;br /&gt;
''&amp;quot;bbbbbcccccdddddaaaaa&amp;quot;'' {{---}} исходная строка&lt;br /&gt;
&lt;br /&gt;
''&amp;quot;10000200003000030000&amp;quot;'' {{---}} строка после MTF &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Частота || Вероятность || Код Хаффмана&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 16 || 4/5 || 0&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 2 || 1/10 || 10&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 1 || 1/20 || 110&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 1 || 1/20 || 111&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
В результате сжатия получаем последовательность длиной &amp;lt;tex&amp;gt;16\cdot1 + 2\cdot2 + 3\cdot2 = 26&amp;lt;/tex&amp;gt; бит. Стоит заметить, что выигрыш от применения [[Арифметическое кодирование|арифметического кодирования]] для данного примера будет еще значительней.&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;br /&gt;
# [http://compression.ru/arctest/descript/bwt-faq.htm Burrows Wheeler Transform FAQ]&lt;br /&gt;
# [http://ru.wikipedia.org/wiki/Move-To-Front Move-To-Front (Википедия)]&lt;br /&gt;
#  Ryabko, B. Ya. ''Data compression by means of a «book stack»'', Problems of Information Transmission, 1980, v. 16: (4), pp.&amp;amp;nbsp;265–269.&lt;br /&gt;
# Ryabko, B. Ya.; Horspool, R. Nigel; Cormack, Gordon V. Comments to: ''«A locally adaptive data compression scheme»'' by J. L. Bentley, D. D. Sleator, R. E. Tarjan and V. K. Wei. Comm. ACM 30 (1987), no. 9, 792—794.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы сжатия ]]&lt;/div&gt;</summary>
		<author><name>Gamezovladislav</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_MTF&amp;diff=44584</id>
		<title>Преобразование MTF</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_MTF&amp;diff=44584"/>
				<updated>2015-01-15T15:00:24Z</updated>
		
		<summary type="html">&lt;p&gt;Gamezovladislav: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Преобразование MTF''' (англ. ''move-to-front'', движение к началу) {{---}} алгоритм кодирования, используемый для предварительной обработки данных (обычно потока байтов) перед сжатием, разработанный для улучшения эффективности последующего кодирования.&lt;br /&gt;
}}&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Изначально каждое возможное значение байта записывается в список (алфавит), в ячейку с номером, равным значению байта, т.е. (0, 1, 2, 3, …, 255). В процессе обработки данных этот список изменяется. По мере поступления очередного символа на выход подается номер элемента, содержащего его значение. После чего этот символ перемещается в начало списка, смещая остальные элементы вправо.&lt;br /&gt;
&lt;br /&gt;
Современные алгоритмы (например, bzip2&amp;lt;ref&amp;gt;[http://ru.wikipedia.org/wiki/Bzip2 {{---}} bzip2]&amp;lt;/ref&amp;gt;) перед алгоритмом MTF используют [[преобразование Барроуза-Уиллера|алгоритм BWT]], поэтому в качестве примера рассмотрим строку &amp;lt;tex&amp;gt;\mathtt{S} = &amp;lt;/tex&amp;gt;''&amp;quot;BCABAAA&amp;quot;'', полученную из строки ''&amp;quot;ABACABA&amp;quot;'' в результате [[Преобразование Барроуза-Уиллера|преобразования Барроуза-Уиллера]]. Первый символ строки &amp;lt;tex&amp;gt;\mathtt{S}&amp;lt;/tex&amp;gt; 'B' является вторым элементом алфавита ''&amp;quot;ABC&amp;quot;'', поэтому на вывод подаётся &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. После перемещения 'B' в начало алфавита тот принимает вид ''&amp;quot;BAC&amp;quot;''. Дальнейшая работа алгоритма показана в таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Список || Вывод&lt;br /&gt;
|-&lt;br /&gt;
| B || A'''B'''C || 1&lt;br /&gt;
|-&lt;br /&gt;
| C || BA'''C''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| A || CB'''A''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| B || AC'''B''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| A || B'''A'''C || 1&lt;br /&gt;
|-&lt;br /&gt;
| A || '''A'''BC || 0&lt;br /&gt;
|-&lt;br /&gt;
| A || '''A'''BC || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Таким образом, результат работы алгоритма: &amp;lt;tex&amp;gt;MTF(\mathtt{S}) = &amp;lt;/tex&amp;gt; ''&amp;quot;1222100&amp;quot;''.  &lt;br /&gt;
&lt;br /&gt;
Вот примерная реализация этого алгоритма. Здесь массив &amp;lt;tex&amp;gt;\mathtt{alphabet}&amp;lt;/tex&amp;gt; хранит количество символов перед символом &amp;lt;tex&amp;gt;\mathtt{S}[\mathtt{i}]&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\mathtt{N}&amp;lt;/tex&amp;gt; {{---}} длина строки &amp;lt;tex&amp;gt;\mathtt{S}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''list&amp;lt;int&amp;gt;''' mtf(N):&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' result(N)&lt;br /&gt;
    '''for''' i = 1 '''to''' N&lt;br /&gt;
       result.append(alphabet[S[i]])&lt;br /&gt;
       помещаем символ S[i] в начало алфавита&lt;br /&gt;
    '''return''' result&lt;br /&gt;
&amp;lt;/code&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Данный алгоритм работает за &amp;lt;tex&amp;gt;O(\mathtt{N} \cdot \mathtt{M})&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\mathtt{N}&amp;lt;/tex&amp;gt; {{---}} размер алфавита, &amp;lt;tex&amp;gt;\mathtt{M}&amp;lt;/tex&amp;gt; {{---}} длина строки, что не очень быстро. Этот алгоритм можно реализовать за &amp;lt;tex&amp;gt;O(\mathtt{N}\log(\mathtt{N+M}))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма за O(N log(N+M)) ==&lt;br /&gt;
&lt;br /&gt;
Пусть дан алфавит размером &amp;lt;tex&amp;gt;\mathtt{M}&amp;lt;/tex&amp;gt; и строка &amp;lt;tex&amp;gt;\mathtt{S}&amp;lt;/tex&amp;gt; длиной &amp;lt;tex&amp;gt;\mathtt{N}&amp;lt;/tex&amp;gt;. Заведем массив &amp;lt;tex&amp;gt;\mathtt{used}[1..\mathtt{N+M}]&amp;lt;/tex&amp;gt; и последние &amp;lt;tex&amp;gt;\mathtt{M}&amp;lt;/tex&amp;gt; ячеек заполним единицами. Запомним для каждого символа алфавита позицию в нашем массиве. Например, &amp;lt;tex&amp;gt;\mathtt{alphabet}['a'] = \mathtt{N}+1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\mathtt{alphabet}['b'] = \mathtt{N}+2&amp;lt;/tex&amp;gt;, ... , &amp;lt;tex&amp;gt;\mathtt{alphabet}['z'] = \mathtt{N+M}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
При обработке &amp;lt;tex&amp;gt;\mathtt{i}&amp;lt;/tex&amp;gt;-го символа посчитаем и выпишем сумму на отрезке &amp;lt;tex&amp;gt;[1, \mathtt{alphabet}[\mathtt{S}[\mathtt{i}]] - 1]&amp;lt;/tex&amp;gt;, поменяем значения ячеек &amp;lt;tex&amp;gt;\mathtt{used}[\mathtt{N-i}+1]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathtt{used}[\mathtt{alphabet}[\mathtt{S}[\mathtt{i}]]]&amp;lt;/tex&amp;gt; местами, также стоит поменять значение в ячейке &amp;lt;tex&amp;gt;\mathtt{alphabet}[\mathtt{S}[\mathtt{i}]]&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;\mathtt{N-i}+1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''list&amp;lt;int&amp;gt;''' mtf(N):&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' result(N)&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' used(N+M)&lt;br /&gt;
    '''for''' i = 1 '''to''' M                                      &amp;lt;font color=darkgreen&amp;gt;//Заполняем последние M ячеек единицами&amp;lt;/font color=darkgreen&amp;gt; &lt;br /&gt;
       used[i+N] = 1&lt;br /&gt;
    '''for''' i = 1 '''to''' N&lt;br /&gt;
       result.append(sum(1, alphabet[S[i]] - 1))        &amp;lt;font color=darkgreen&amp;gt;//Запоминаем ответ&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
       swap(used[N-i+1], used[alphabet[S[i]]])          &amp;lt;font color=darkgreen&amp;gt;//Меняем значения&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
       alphabet[S[i]] = N-i+1                           &amp;lt;font color=darkgreen&amp;gt;//Изменяем позицию символа в массиве&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
    '''return''' result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функцию &amp;lt;tex&amp;gt;sum&amp;lt;/tex&amp;gt; можно реализовывать по-разному.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' sum(left, right)&lt;br /&gt;
    result = 0&lt;br /&gt;
    '''for''' i = left '''to''' right&lt;br /&gt;
       result = result + used[i]&lt;br /&gt;
    '''return''' result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Такая реализация работает за &amp;lt;tex&amp;gt;O(right-left)&amp;lt;/tex&amp;gt;, общая сложность алгоритма равна &amp;lt;tex&amp;gt;O(\mathtt{N} \cdot \mathtt{M})&amp;lt;/tex&amp;gt; Но можно находить сумму на отрезке при помощи [[Дерево_отрезков._Построение | дерева отрезков]], что сократит время работы до &amp;lt;tex&amp;gt;O(\log(\mathtt{right-left}))&amp;lt;/tex&amp;gt;. Итого, общая сложность будет равна &amp;lt;tex&amp;gt;O(\mathtt{N}\log(\mathtt{N+M}))&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
== Обратное преобразование ==&lt;br /&gt;
&lt;br /&gt;
Пусть даны строка &amp;lt;tex&amp;gt;\mathtt{S} = &amp;lt;/tex&amp;gt;''&amp;quot;1222100&amp;quot;'' и исходный алфавит ''&amp;quot;ABC&amp;quot;''. Символ с номером &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; в алфавите {{---}} это 'B'. На вывод подаётся 'B', и этот символ перемещается в начало алфавита. Символ с номером &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; в алфавите {{---}} это 'A', поэтому 'A' подается на вывод и перемещается в начало алфавита. Дальнейшее преобразование происходит аналогично.&lt;br /&gt;
&lt;br /&gt;
{| class =&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Список || Вывод&lt;br /&gt;
|-&lt;br /&gt;
| 1 || A'''B'''C || B&lt;br /&gt;
|-&lt;br /&gt;
| 2 || BA'''C''' || C&lt;br /&gt;
|-&lt;br /&gt;
| 2 || CB'''A''' || A&lt;br /&gt;
|-&lt;br /&gt;
| 2 || AC'''B''' || B&lt;br /&gt;
|-&lt;br /&gt;
| 1 || B'''A'''C || A&lt;br /&gt;
|-&lt;br /&gt;
| 0 || '''A'''BC || A&lt;br /&gt;
|-&lt;br /&gt;
| 0 || '''A'''BC || A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Значит, исходная строка &amp;lt;tex&amp;gt;MTF^{-1}(\mathtt{S}) = &amp;lt;/tex&amp;gt;''&amp;quot;BCABAAA&amp;quot;''.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
&lt;br /&gt;
Этот метод позволяет легко преобразовать данные, насыщенные длинными повторами разных символов в блок данных, самыми частыми символами которого будут нули. Без MTF нас подстерегают разного рода трудности в решении проблемы адаптации к данным, поскольку в разных местах данных, полученных на выходе [[Преобразование Барроуза-Уиллера|BWT-преобразования]], разные символы являются преобладающими. Зачастую мы встречаемся с последовательностями типа &amp;quot;bbbbbcccccdddddaaaaa&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Попробуем сжать эту последовательность при помощи, например, [[Алгоритм Хаффмана|метода Хаффмана]]. Вероятности всех четырех символов в данном примере равны &amp;lt;tex&amp;gt;1/4&amp;lt;/tex&amp;gt;. Легко посчитать, что в результате кодирования мы получим последовательность длиной &amp;lt;tex&amp;gt;20\cdot2 = 40&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Теперь проделаем то же самое со строкой, подвергнутой MTF-преобразованию (предположим, начальный алфавит выглядит как ''&amp;quot;abcd&amp;quot;''). &lt;br /&gt;
&lt;br /&gt;
''&amp;quot;bbbbbcccccdddddaaaaa&amp;quot;'' {{---}} исходная строка&lt;br /&gt;
&lt;br /&gt;
''&amp;quot;10000200003000030000&amp;quot;'' {{---}} строка после MTF &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Частота || Вероятность || Код Хаффмана&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 16 || 4/5 || 0&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 2 || 1/10 || 10&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 1 || 1/20 || 110&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 1 || 1/20 || 111&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
В результате сжатия получаем последовательность длиной &amp;lt;tex&amp;gt;16\cdot1 + 2\cdot2 + 3\cdot2 = 26&amp;lt;/tex&amp;gt; бит. Стоит заметить, что выигрыш от применения [[Арифметическое кодирование|арифметического кодирования]] для данного примера будет еще значительней.&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;br /&gt;
* [http://compression.ru/arctest/descript/bwt-faq.htm Burrows Wheeler Transform FAQ]&lt;br /&gt;
&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Move-To-Front Move-To-Front (Википедия)]&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
#  Ryabko, B. Ya. ''Data compression by means of a «book stack»'', Problems of Information Transmission, 1980, v. 16: (4), pp.&amp;amp;nbsp;265–269.&lt;br /&gt;
# Ryabko, B. Ya.; Horspool, R. Nigel; Cormack, Gordon V. Comments to: ''«A locally adaptive data compression scheme»'' by J. L. Bentley, D. D. Sleator, R. E. Tarjan and V. K. Wei. Comm. ACM 30 (1987), no. 9, 792—794.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы сжатия ]]&lt;/div&gt;</summary>
		<author><name>Gamezovladislav</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_MTF&amp;diff=44583</id>
		<title>Преобразование MTF</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_MTF&amp;diff=44583"/>
				<updated>2015-01-15T14:59:30Z</updated>
		
		<summary type="html">&lt;p&gt;Gamezovladislav: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Преобразование MTF''' (англ. ''move-to-front'', движение к началу) {{---}} алгоритм кодирования, используемый для предварительной обработки данных (обычно потока байтов) перед сжатием, разработанный для улучшения эффективности последующего кодирования.&lt;br /&gt;
}}&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Изначально каждое возможное значение байта записывается в список (алфавит), в ячейку с номером, равным значению байта, т.е. (0, 1, 2, 3, …, 255). В процессе обработки данных этот список изменяется. По мере поступления очередного символа на выход подается номер элемента, содержащего его значение. После чего этот символ перемещается в начало списка, смещая остальные элементы вправо.&lt;br /&gt;
&lt;br /&gt;
Современные алгоритмы (например, bzip2&amp;lt;ref&amp;gt;[http://ru.wikipedia.org/wiki/Bzip2 {{---}} bzip2]&amp;lt;/ref&amp;gt;) перед алгоритмом MTF используют [[преобразование Барроуза-Уиллера|алгоритм BWT]], поэтому в качестве примера рассмотрим строку &amp;lt;tex&amp;gt;\mathtt{S} = &amp;lt;/tex&amp;gt;''&amp;quot;BCABAAA&amp;quot;'', полученную из строки ''&amp;quot;ABACABA&amp;quot;'' в результате [[Преобразование Барроуза-Уиллера|преобразования Барроуза-Уиллера]]. Первый символ строки &amp;lt;tex&amp;gt;\mathtt{S}&amp;lt;/tex&amp;gt; 'B' является вторым элементом алфавита ''&amp;quot;ABC&amp;quot;'', поэтому на вывод подаётся &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. После перемещения 'B' в начало алфавита тот принимает вид ''&amp;quot;BAC&amp;quot;''. Дальнейшая работа алгоритма показана в таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Список || Вывод&lt;br /&gt;
|-&lt;br /&gt;
| B || A'''B'''C || 1&lt;br /&gt;
|-&lt;br /&gt;
| C || BA'''C''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| A || CB'''A''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| B || AC'''B''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| A || B'''A'''C || 1&lt;br /&gt;
|-&lt;br /&gt;
| A || '''A'''BC || 0&lt;br /&gt;
|-&lt;br /&gt;
| A || '''A'''BC || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Таким образом, результат работы алгоритма: &amp;lt;tex&amp;gt;MTF(\mathtt{S}) = &amp;lt;/tex&amp;gt; ''&amp;quot;1222100&amp;quot;''.  &lt;br /&gt;
&lt;br /&gt;
Вот примерная реализация этого алгоритма. Здесь массив &amp;lt;tex&amp;gt;\mathtt{alphabet}&amp;lt;/tex&amp;gt; хранит количество символов перед символом &amp;lt;tex&amp;gt;\mathtt{S}[\mathtt{i}]&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;/mathtt{N}&amp;lt;/tex&amp;gt; {{---}} длина строки &amp;lt;tex&amp;gt;/mathtt{S}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''list&amp;lt;int&amp;gt;''' mtf(N):&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' result(N)&lt;br /&gt;
    '''for''' i = 1 '''to''' N&lt;br /&gt;
       result.append(alphabet[S[i]])&lt;br /&gt;
       помещаем символ S[i] в начало алфавита&lt;br /&gt;
    '''return''' result&lt;br /&gt;
&amp;lt;/code&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Данный алгоритм работает за &amp;lt;tex&amp;gt;O(\mathtt{N} \cdot \mathtt{M})&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\mathtt{N}&amp;lt;/tex&amp;gt; {{---}} размер алфавита, &amp;lt;tex&amp;gt;\mathtt{M}&amp;lt;/tex&amp;gt; {{---}} длина строки, что не очень быстро. Этот алгоритм можно реализовать за &amp;lt;tex&amp;gt;O(\mathtt{N}\log(\mathtt{N+M}))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма за O(N log(N+M)) ==&lt;br /&gt;
&lt;br /&gt;
Пусть дан алфавит размером &amp;lt;tex&amp;gt;\mathtt{M}&amp;lt;/tex&amp;gt; и строка &amp;lt;tex&amp;gt;\mathtt{S}&amp;lt;/tex&amp;gt; длиной &amp;lt;tex&amp;gt;\mathtt{N}&amp;lt;/tex&amp;gt;. Заведем массив &amp;lt;tex&amp;gt;\mathtt{used}[1..\mathtt{N+M}]&amp;lt;/tex&amp;gt; и последние &amp;lt;tex&amp;gt;\mathtt{M}&amp;lt;/tex&amp;gt; ячеек заполним единицами. Запомним для каждого символа алфавита позицию в нашем массиве. Например, &amp;lt;tex&amp;gt;\mathtt{alphabet}['a'] = \mathtt{N}+1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\mathtt{alphabet}['b'] = \mathtt{N}+2&amp;lt;/tex&amp;gt;, ... , &amp;lt;tex&amp;gt;\mathtt{alphabet}['z'] = \mathtt{N+M}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
При обработке &amp;lt;tex&amp;gt;\mathtt{i}&amp;lt;/tex&amp;gt;-го символа посчитаем и выпишем сумму на отрезке &amp;lt;tex&amp;gt;[1, \mathtt{alphabet}[\mathtt{S}[\mathtt{i}]] - 1]&amp;lt;/tex&amp;gt;, поменяем значения ячеек &amp;lt;tex&amp;gt;\mathtt{used}[\mathtt{N-i}+1]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathtt{used}[\mathtt{alphabet}[\mathtt{S}[\mathtt{i}]]]&amp;lt;/tex&amp;gt; местами, также стоит поменять значение в ячейке &amp;lt;tex&amp;gt;\mathtt{alphabet}[\mathtt{S}[\mathtt{i}]]&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;\mathtt{N-i}+1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''list&amp;lt;int&amp;gt;''' mtf(N):&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' result(N)&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' used(N+M)&lt;br /&gt;
    '''for''' i = 1 '''to''' M                                      &amp;lt;font color=darkgreen&amp;gt;//Заполняем последние M ячеек единицами&amp;lt;/font color=darkgreen&amp;gt; &lt;br /&gt;
       used[i+N] = 1&lt;br /&gt;
    '''for''' i = 1 '''to''' N&lt;br /&gt;
       result.append(sum(1, alphabet[S[i]] - 1))        &amp;lt;font color=darkgreen&amp;gt;//Запоминаем ответ&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
       swap(used[N-i+1], used[alphabet[S[i]]])          &amp;lt;font color=darkgreen&amp;gt;//Меняем значения&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
       alphabet[S[i]] = N-i+1                           &amp;lt;font color=darkgreen&amp;gt;//Изменяем позицию символа в массиве&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
    '''return''' result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функцию &amp;lt;tex&amp;gt;sum&amp;lt;/tex&amp;gt; можно реализовывать по-разному.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' sum(left, right)&lt;br /&gt;
    result = 0&lt;br /&gt;
    '''for''' i = left '''to''' right&lt;br /&gt;
       result = result + used[i]&lt;br /&gt;
    '''return''' result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Такая реализация работает за &amp;lt;tex&amp;gt;O(right-left)&amp;lt;/tex&amp;gt;, общая сложность алгоритма равна &amp;lt;tex&amp;gt;O(\mathtt{N} \cdot \mathtt{M})&amp;lt;/tex&amp;gt; Но можно находить сумму на отрезке при помощи [[Дерево_отрезков._Построение | дерева отрезков]], что сократит время работы до &amp;lt;tex&amp;gt;O(\log(\mathtt{right-left}))&amp;lt;/tex&amp;gt;. Итого, общая сложность будет равна &amp;lt;tex&amp;gt;O(\mathtt{N}\log(\mathtt{N+M}))&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
== Обратное преобразование ==&lt;br /&gt;
&lt;br /&gt;
Пусть даны строка &amp;lt;tex&amp;gt;\mathtt{S} = &amp;lt;/tex&amp;gt;''&amp;quot;1222100&amp;quot;'' и исходный алфавит ''&amp;quot;ABC&amp;quot;''. Символ с номером &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; в алфавите {{---}} это 'B'. На вывод подаётся 'B', и этот символ перемещается в начало алфавита. Символ с номером &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; в алфавите {{---}} это 'A', поэтому 'A' подается на вывод и перемещается в начало алфавита. Дальнейшее преобразование происходит аналогично.&lt;br /&gt;
&lt;br /&gt;
{| class =&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Список || Вывод&lt;br /&gt;
|-&lt;br /&gt;
| 1 || A'''B'''C || B&lt;br /&gt;
|-&lt;br /&gt;
| 2 || BA'''C''' || C&lt;br /&gt;
|-&lt;br /&gt;
| 2 || CB'''A''' || A&lt;br /&gt;
|-&lt;br /&gt;
| 2 || AC'''B''' || B&lt;br /&gt;
|-&lt;br /&gt;
| 1 || B'''A'''C || A&lt;br /&gt;
|-&lt;br /&gt;
| 0 || '''A'''BC || A&lt;br /&gt;
|-&lt;br /&gt;
| 0 || '''A'''BC || A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Значит, исходная строка &amp;lt;tex&amp;gt;MTF^{-1}(\mathtt{S}) = &amp;lt;/tex&amp;gt;''&amp;quot;BCABAAA&amp;quot;''.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
&lt;br /&gt;
Этот метод позволяет легко преобразовать данные, насыщенные длинными повторами разных символов в блок данных, самыми частыми символами которого будут нули. Без MTF нас подстерегают разного рода трудности в решении проблемы адаптации к данным, поскольку в разных местах данных, полученных на выходе [[Преобразование Барроуза-Уиллера|BWT-преобразования]], разные символы являются преобладающими. Зачастую мы встречаемся с последовательностями типа &amp;quot;bbbbbcccccdddddaaaaa&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Попробуем сжать эту последовательность при помощи, например, [[Алгоритм Хаффмана|метода Хаффмана]]. Вероятности всех четырех символов в данном примере равны &amp;lt;tex&amp;gt;1/4&amp;lt;/tex&amp;gt;. Легко посчитать, что в результате кодирования мы получим последовательность длиной &amp;lt;tex&amp;gt;20\cdot2 = 40&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Теперь проделаем то же самое со строкой, подвергнутой MTF-преобразованию (предположим, начальный алфавит выглядит как ''&amp;quot;abcd&amp;quot;''). &lt;br /&gt;
&lt;br /&gt;
''&amp;quot;bbbbbcccccdddddaaaaa&amp;quot;'' {{---}} исходная строка&lt;br /&gt;
&lt;br /&gt;
''&amp;quot;10000200003000030000&amp;quot;'' {{---}} строка после MTF &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Частота || Вероятность || Код Хаффмана&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 16 || 4/5 || 0&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 2 || 1/10 || 10&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 1 || 1/20 || 110&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 1 || 1/20 || 111&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
В результате сжатия получаем последовательность длиной &amp;lt;tex&amp;gt;16\cdot1 + 2\cdot2 + 3\cdot2 = 26&amp;lt;/tex&amp;gt; бит. Стоит заметить, что выигрыш от применения [[Арифметическое кодирование|арифметического кодирования]] для данного примера будет еще значительней.&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;br /&gt;
* [http://compression.ru/arctest/descript/bwt-faq.htm Burrows Wheeler Transform FAQ]&lt;br /&gt;
&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Move-To-Front Move-To-Front (Википедия)]&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
#  Ryabko, B. Ya. ''Data compression by means of a «book stack»'', Problems of Information Transmission, 1980, v. 16: (4), pp.&amp;amp;nbsp;265–269.&lt;br /&gt;
# Ryabko, B. Ya.; Horspool, R. Nigel; Cormack, Gordon V. Comments to: ''«A locally adaptive data compression scheme»'' by J. L. Bentley, D. D. Sleator, R. E. Tarjan and V. K. Wei. Comm. ACM 30 (1987), no. 9, 792—794.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы сжатия ]]&lt;/div&gt;</summary>
		<author><name>Gamezovladislav</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_MTF&amp;diff=44565</id>
		<title>Преобразование MTF</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_MTF&amp;diff=44565"/>
				<updated>2015-01-15T13:23:04Z</updated>
		
		<summary type="html">&lt;p&gt;Gamezovladislav: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Преобразование MTF''' (англ. ''move-to-front'', движение к началу) {{---}} алгоритм кодирования, используемый для предварительной обработки данных (обычно потока байтов) перед сжатием, разработанный для улучшения эффективности последующего кодирования.&lt;br /&gt;
}}&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Изначально каждое возможное значение байта записывается в список (алфавит), в ячейку с номером, равным значению байта, т.е. (0, 1, 2, 3, …, 255). В процессе обработки данных этот список изменяется. По мере поступления очередного символа на выход подается номер элемента, содержащего его значение. После чего этот символ перемещается в начало списка, смещая остальные элементы вправо.&lt;br /&gt;
&lt;br /&gt;
Современные алгоритмы (например, bzip2&amp;lt;ref&amp;gt;[http://ru.wikipedia.org/wiki/Bzip2 {{---}} bzip2]&amp;lt;/ref&amp;gt;) перед алгоритмом MTF используют [[преобразование Барроуза-Уиллера|алгоритм BWT]], поэтому в качестве примера рассмотрим строку &amp;lt;tex&amp;gt;\mathtt{S} = &amp;lt;/tex&amp;gt;''&amp;quot;BCABAAA&amp;quot;'', полученную из строки ''&amp;quot;ABACABA&amp;quot;'' в результате [[Преобразование Барроуза-Уиллера|преобразования Барроуза-Уиллера]]. Первый символ строки &amp;lt;tex&amp;gt;\mathtt{S}&amp;lt;/tex&amp;gt; 'B' является вторым элементом алфавита ''&amp;quot;ABC&amp;quot;'', поэтому на вывод подаётся &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. После перемещения 'B' в начало алфавита тот принимает вид ''&amp;quot;BAC&amp;quot;''. Дальнейшая работа алгоритма показана в таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Список || Вывод&lt;br /&gt;
|-&lt;br /&gt;
| B || A'''B'''C || 1&lt;br /&gt;
|-&lt;br /&gt;
| C || BA'''C''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| A || CB'''A''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| B || AC'''B''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| A || B'''A'''C || 1&lt;br /&gt;
|-&lt;br /&gt;
| A || '''A'''BC || 0&lt;br /&gt;
|-&lt;br /&gt;
| A || '''A'''BC || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Таким образом, результат работы алгоритма: &amp;lt;tex&amp;gt;MTF(\mathtt{S}) = &amp;lt;/tex&amp;gt; ''&amp;quot;1222100&amp;quot;''.    &lt;br /&gt;
&lt;br /&gt;
Данный алгоритм работает за &amp;lt;tex&amp;gt;O(\mathtt{N} \cdot \mathtt{M})&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\mathtt{N}&amp;lt;/tex&amp;gt; {{---}} размер алфавита, &amp;lt;tex&amp;gt;\mathtt{M}&amp;lt;/tex&amp;gt; {{---}} длина строки, что не очень быстро. Этот алгоритм можно реализовать за &amp;lt;tex&amp;gt;O(\mathtt{N}\log(\mathtt{N+M}))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма за O(N log(N+M)) ==&lt;br /&gt;
&lt;br /&gt;
=== Идея ===&lt;br /&gt;
&lt;br /&gt;
Пусть дан алфавит размером &amp;lt;tex&amp;gt;\mathtt{M}&amp;lt;/tex&amp;gt; и строка &amp;lt;tex&amp;gt;\mathtt{S}&amp;lt;/tex&amp;gt; длиной &amp;lt;tex&amp;gt;\mathtt{N}&amp;lt;/tex&amp;gt;. Заведем массив &amp;lt;tex&amp;gt;\mathtt{used}[1..\mathtt{N+M}]&amp;lt;/tex&amp;gt; и последние &amp;lt;tex&amp;gt;\mathtt{M}&amp;lt;/tex&amp;gt; ячеек заполним единицами. Запомним для каждого символа алфавита позицию в нашем массиве. Например, &amp;lt;tex&amp;gt;\mathtt{alphabet}['a'] = \mathtt{N}+1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\mathtt{alphabet}['b'] = \mathtt{N}+2&amp;lt;/tex&amp;gt;, ... , &amp;lt;tex&amp;gt;\mathtt{alphabet}['z'] = \mathtt{N+M}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
При обработке &amp;lt;tex&amp;gt;\mathtt{i}&amp;lt;/tex&amp;gt;-го символа посчитаем и выпишем сумму на отрезке &amp;lt;tex&amp;gt;[1, \mathtt{alphabet}[\mathtt{S}[\mathtt{i}]] - 1]&amp;lt;/tex&amp;gt;, поменяем значения ячеек &amp;lt;tex&amp;gt;\mathtt{used}[\mathtt{N-i}+1]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathtt{used}[\mathtt{alphabet}[\mathtt{S}[\mathtt{i}]]]&amp;lt;/tex&amp;gt; местами, также стоит поменять значение в ячейке &amp;lt;tex&amp;gt;\mathtt{alphabet}[\mathtt{S}[\mathtt{i}]]&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;\mathtt{N-i}+1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Чтобы добиться сложности  алгоритма &amp;lt;tex&amp;gt;O(\mathtt{N}&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt;\log&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt;(\mathtt{N+M}))&amp;lt;/tex&amp;gt; нужно использовать дерево отрезков или подобное.&lt;br /&gt;
&lt;br /&gt;
=== Псевдокод ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''list&amp;lt;int&amp;gt;''' mtf(N):&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' result(N)&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' used(N+M)&lt;br /&gt;
    '''for''' i = 1 '''to''' M                                      &amp;lt;font color=darkgreen&amp;gt;//Заполняем последние M ячеек единицами&amp;lt;/font color=darkgreen&amp;gt; &lt;br /&gt;
       used[i+N] = 1&lt;br /&gt;
    '''for''' i = 1 '''to''' N&lt;br /&gt;
       result.append(sum(1, alphabet[S[i]] - 1))        &amp;lt;font color=darkgreen&amp;gt;//Запоминаем ответ&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
       swap(used[N-i+1], used[alphabet[S[i]]])          &amp;lt;font color=darkgreen&amp;gt;//Меняем значения&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
       alphabet[S[i]] = N-i+1                           &amp;lt;font color=darkgreen&amp;gt;//Изменяем позицию символа в массиве&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
    '''return''' result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Обратное преобразование ==&lt;br /&gt;
&lt;br /&gt;
Пусть даны строка &amp;lt;tex&amp;gt;\mathtt{S} = &amp;lt;/tex&amp;gt;''&amp;quot;1222100&amp;quot;'' и исходный алфавит ''&amp;quot;ABC&amp;quot;''. Символ с номером &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; в алфавите {{---}} это 'B'. На вывод подаётся 'B', и этот символ перемещается в начало алфавита. Символ с номером &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; в алфавите {{---}} это 'A', поэтому 'A' подается на вывод и перемещается в начало алфавита. Дальнейшее преобразование происходит аналогично.&lt;br /&gt;
&lt;br /&gt;
{| class =&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Список || Вывод&lt;br /&gt;
|-&lt;br /&gt;
| 1 || A'''B'''C || B&lt;br /&gt;
|-&lt;br /&gt;
| 2 || BA'''C''' || C&lt;br /&gt;
|-&lt;br /&gt;
| 2 || CB'''A''' || A&lt;br /&gt;
|-&lt;br /&gt;
| 2 || AC'''B''' || B&lt;br /&gt;
|-&lt;br /&gt;
| 1 || B'''A'''C || A&lt;br /&gt;
|-&lt;br /&gt;
| 0 || '''A'''BC || A&lt;br /&gt;
|-&lt;br /&gt;
| 0 || '''A'''BC || A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Значит, исходная строка &amp;lt;tex&amp;gt;MTF^{-1}(\mathtt{S}) = &amp;lt;/tex&amp;gt;''&amp;quot;BCABAAA&amp;quot;''.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
&lt;br /&gt;
Этот метод позволяет легко преобразовать данные, насыщенные длинными повторами разных символов в блок данных, самыми частыми символами которого будут нули. Без MTF нас подстерегают разного рода трудности в решении проблемы адаптации к данным, поскольку в разных местах данных, полученных на выходе [[Преобразование Барроуза-Уиллера|BWT-преобразования]], разные символы являются преобладающими. Зачастую мы встречаемся с последовательностями типа &amp;quot;bbbbbcccccdddddaaaaa&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Попробуем сжать эту последовательность при помощи, например, [[Алгоритм Хаффмана|метода Хаффмана]]. Вероятности всех четырех символов в данном примере равны &amp;lt;tex&amp;gt;1/4&amp;lt;/tex&amp;gt;. Легко посчитать, что в результате кодирования мы получим последовательность длиной &amp;lt;tex&amp;gt;20\cdot2 = 40&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Теперь проделаем то же самое со строкой, подвергнутой MTF-преобразованию (предположим, начальный алфавит выглядит как ''&amp;quot;abcd&amp;quot;''). &lt;br /&gt;
&lt;br /&gt;
''&amp;quot;bbbbbcccccdddddaaaaa&amp;quot;'' {{---}} исходная строка&lt;br /&gt;
&lt;br /&gt;
''&amp;quot;10000200003000030000&amp;quot;'' {{---}} строка после MTF &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Частота || Вероятность || Код Хаффмана&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 16 || 4/5 || 0&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 2 || 1/10 || 10&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 1 || 1/20 || 110&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 1 || 1/20 || 111&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
В результате сжатия получаем последовательность длиной &amp;lt;tex&amp;gt;16\cdot1 + 2\cdot2 + 3\cdot2 = 26&amp;lt;/tex&amp;gt; бит. Стоит заметить, что выигрыш от применения [[Арифметическое кодирование|арифметического кодирования]] для данного примера будет еще значительней.&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;br /&gt;
* [http://compression.ru/arctest/descript/bwt-faq.htm Burrows Wheeler Transform FAQ]&lt;br /&gt;
&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Move-To-Front Move-To-Front (Википедия)]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы сжатия ]]&lt;/div&gt;</summary>
		<author><name>Gamezovladislav</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_MTF&amp;diff=44563</id>
		<title>Преобразование MTF</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_MTF&amp;diff=44563"/>
				<updated>2015-01-15T13:21:06Z</updated>
		
		<summary type="html">&lt;p&gt;Gamezovladislav: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Преобразование MTF''' (англ. ''move-to-front'', движение к началу) {{---}} алгоритм кодирования, используемый для предварительной обработки данных (обычно потока байтов) перед сжатием, разработанный для улучшения эффективности последующего кодирования.&lt;br /&gt;
}}&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Изначально каждое возможное значение байта записывается в список (алфавит), в ячейку с номером, равным значению байта, т.е. (0, 1, 2, 3, …, 255). В процессе обработки данных этот список изменяется. По мере поступления очередного символа на выход подается номер элемента, содержащего его значение. После чего этот символ перемещается в начало списка, смещая остальные элементы вправо.&lt;br /&gt;
&lt;br /&gt;
Современные алгоритмы (например, bzip2&amp;lt;ref&amp;gt;[http://ru.wikipedia.org/wiki/Bzip2 {{---}} bzip2]&amp;lt;/ref&amp;gt;) перед алгоритмом MTF используют [[преобразование Барроуза-Уиллера|алгоритм BWT]], поэтому в качестве примера рассмотрим строку &amp;lt;tex&amp;gt;\mathtt{S} = &amp;lt;/tex&amp;gt;''&amp;quot;BCABAAA&amp;quot;'', полученную из строки ''&amp;quot;ABACABA&amp;quot;'' в результате [[Преобразование Барроуза-Уиллера|преобразования Барроуза-Уиллера]]. Первый символ строки &amp;lt;tex&amp;gt;\mathtt{S}&amp;lt;/tex&amp;gt; 'B' является вторым элементом алфавита ''&amp;quot;ABC&amp;quot;'', поэтому на вывод подаётся &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. После перемещения 'B' в начало алфавита тот принимает вид ''&amp;quot;BAC&amp;quot;''. Дальнейшая работа алгоритма показана в таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Список || Вывод&lt;br /&gt;
|-&lt;br /&gt;
| B || A'''B'''C || 1&lt;br /&gt;
|-&lt;br /&gt;
| C || BA'''C''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| A || CB'''A''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| B || AC'''B''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| A || B'''A'''C || 1&lt;br /&gt;
|-&lt;br /&gt;
| A || '''A'''BC || 0&lt;br /&gt;
|-&lt;br /&gt;
| A || '''A'''BC || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Таким образом, результат работы алгоритма: &amp;lt;tex&amp;gt;MTF(\mathtt{S}) = &amp;lt;/tex&amp;gt; ''&amp;quot;1222100&amp;quot;''.    &lt;br /&gt;
&lt;br /&gt;
Данный алгоритм работает за &amp;lt;tex&amp;gt;O(\mathtt{N} \cdot \mathtt{M})&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\mathtt{N}&amp;lt;/tex&amp;gt; {{---}} размер алфавита, &amp;lt;tex&amp;gt;\mathtt{M}&amp;lt;/tex&amp;gt; {{---}} длина строки, что не очень быстро. Этот алгоритм можно реализовать за &amp;lt;tex&amp;gt;O(\mathtt{N}\log(\mathtt{N+M}))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма за O(N log(N+M)) ==&lt;br /&gt;
&lt;br /&gt;
=== Идея ===&lt;br /&gt;
&lt;br /&gt;
Пусть дан алфавит размером &amp;lt;tex&amp;gt;\mathtt{M}&amp;lt;/tex&amp;gt; и строка &amp;lt;tex&amp;gt;\mathtt{S}&amp;lt;/tex&amp;gt; длиной &amp;lt;tex&amp;gt;\mathtt{N}&amp;lt;/tex&amp;gt;. Заведем массив &amp;lt;tex&amp;gt;\mathtt{used}[1..\mathtt{N+M}]&amp;lt;/tex&amp;gt; и последние &amp;lt;tex&amp;gt;\mathtt{M}&amp;lt;/tex&amp;gt; ячеек заполним единицами. Запомним для каждого символа алфавита позицию в нашем массиве. Например, &amp;lt;tex&amp;gt;\mathtt{alphabet}['a'] = \mathtt{N}+1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\mathtt{alphabet}['b'] = \mathtt{N}+2&amp;lt;/tex&amp;gt;, ... , &amp;lt;tex&amp;gt;\mathtt{alphabet}['z'] = \mathtt{N+M}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
При обработке &amp;lt;tex&amp;gt;\mathtt{i}&amp;lt;/tex&amp;gt;-го символа посчитаем и выпишем сумму на отрезке &amp;lt;tex&amp;gt;[1, \mathtt{alphabet}[\mathtt{S}[\mathtt{i}]] - 1]&amp;lt;/tex&amp;gt;, поменяем значения ячеек &amp;lt;tex&amp;gt;\mathtt{used}[\mathtt{N-i}+1]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathtt{used}[\mathtt{alphabet}[\mathtt{S}[\mathtt{i}]]]&amp;lt;/tex&amp;gt; местами, также стоит поменять значение в ячейке &amp;lt;tex&amp;gt;\mathtt{alphabet}[\mathtt{S}[\mathtt{i}]]&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;\mathtt{N-i}+1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Чтобы добиться сложности  алгоритма &amp;lt;tex&amp;gt;O(\mathtt{N}&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt;\log&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt;(\mathtt{N+M}))&amp;lt;/tex&amp;gt; нужно использовать дерево отрезков или подобное.&lt;br /&gt;
&lt;br /&gt;
=== Псевдокод ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''list&amp;lt;int&amp;gt;''' mtf(N):&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' result(N)&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' used(N+M)&lt;br /&gt;
    '''for''' i = 1 '''to''' M                                      &amp;lt;font color=darkgreen&amp;gt;//Заполняем последние M ячеек единицами&amp;lt;/font color=darkgreen&amp;gt; &lt;br /&gt;
       used[i+N] = 1&lt;br /&gt;
    '''for''' i = 1 '''to''' N&lt;br /&gt;
       result.append(sum(1, alphabet[S[i]] - 1))        &amp;lt;font color=darkgreen&amp;gt;//Запоминаем ответ&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
       swap(used[N-i+1], used[alphabet[S[i]]])          &amp;lt;font color=darkgreen&amp;gt;//Меняем значения&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
       alphabet[S[i]] = N-i+1                           &amp;lt;font color=darkgreen&amp;gt;//Изменяем позицию символа в массиве&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
    '''return''' result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Обратное преобразование ==&lt;br /&gt;
&lt;br /&gt;
Пусть даны строка &amp;lt;tex&amp;gt;\mathtt{s} = &amp;lt;/tex&amp;gt;''&amp;quot;1222100&amp;quot;'' и исходный алфавит ''&amp;quot;ABC&amp;quot;''. Символ с номером &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; в алфавите {{---}} это 'B'. На вывод подаётся 'B', и этот символ перемещается в начало алфавита. Символ с номером &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; в алфавите {{---}} это 'A', поэтому 'A' подается на вывод и перемещается в начало алфавита. Дальнейшее преобразование происходит аналогично.&lt;br /&gt;
&lt;br /&gt;
{| class =&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Список || Вывод&lt;br /&gt;
|-&lt;br /&gt;
| 1 || A'''B'''C || B&lt;br /&gt;
|-&lt;br /&gt;
| 2 || BA'''C''' || C&lt;br /&gt;
|-&lt;br /&gt;
| 2 || CB'''A''' || A&lt;br /&gt;
|-&lt;br /&gt;
| 2 || AC'''B''' || B&lt;br /&gt;
|-&lt;br /&gt;
| 1 || B'''A'''C || A&lt;br /&gt;
|-&lt;br /&gt;
| 0 || '''A'''BC || A&lt;br /&gt;
|-&lt;br /&gt;
| 0 || '''A'''BC || A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Значит, исходная строка &amp;lt;tex&amp;gt;MTF^{-1}(\mathtt{S}) = &amp;lt;/tex&amp;gt;''&amp;quot;BCABAAA&amp;quot;''.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
&lt;br /&gt;
Этот метод позволяет легко преобразовать данные, насыщенные длинными повторами разных символов в блок данных, самыми частыми символами которого будут нули. Без MTF нас подстерегают разного рода трудности в решении проблемы адаптации к данным, поскольку в разных местах данных, полученных на выходе [[Преобразование Барроуза-Уиллера|BWT-преобразования]], разные символы являются преобладающими. Зачастую мы встречаемся с последовательностями типа &amp;quot;bbbbbcccccdddddaaaaa&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Попробуем сжать эту последовательность при помощи, например, [[Алгоритм Хаффмана|метода Хаффмана]]. Вероятности всех четырех символов в данном примере равны &amp;lt;tex&amp;gt;1/4&amp;lt;/tex&amp;gt;. Легко посчитать, что в результате кодирования мы получим последовательность длиной &amp;lt;tex&amp;gt;20\cdot2 = 40&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Теперь проделаем то же самое со строкой, подвергнутой MTF-преобразованию (предположим, начальный алфавит выглядит как ''&amp;quot;abcd&amp;quot;''). &lt;br /&gt;
&lt;br /&gt;
''&amp;quot;bbbbbcccccdddddaaaaa&amp;quot;'' {{---}} исходная строка&lt;br /&gt;
&lt;br /&gt;
''&amp;quot;10000200003000030000&amp;quot;'' {{---}} строка после MTF &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Частота || Вероятность || Код Хаффмана&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 16 || 4/5 || 0&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 2 || 1/10 || 10&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 1 || 1/20 || 110&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 1 || 1/20 || 111&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
В результате сжатия получаем последовательность длиной &amp;lt;tex&amp;gt;16\cdot1 + 2\cdot2 + 3\cdot2 = 26&amp;lt;/tex&amp;gt; бит. Стоит заметить, что выигрыш от применения [[Арифметическое кодирование|арифметического кодирования]] для данного примера будет еще значительней.&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;br /&gt;
* [http://compression.ru/arctest/descript/bwt-faq.htm Burrows Wheeler Transform FAQ]&lt;br /&gt;
&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Move-To-Front Move-To-Front (Википедия)]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы сжатия ]]&lt;/div&gt;</summary>
		<author><name>Gamezovladislav</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_MTF&amp;diff=44560</id>
		<title>Преобразование MTF</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_MTF&amp;diff=44560"/>
				<updated>2015-01-15T12:56:57Z</updated>
		
		<summary type="html">&lt;p&gt;Gamezovladislav: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Преобразование MTF''' (англ. ''move-to-front'', движение к началу) {{---}} алгоритм кодирования, используемый для предварительной обработки данных (обычно потока байтов) перед сжатием, разработанный для улучшения эффективности последующего кодирования.&lt;br /&gt;
}}&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Изначально каждое возможное значение байта записывается в список (алфавит), в ячейку с номером, равным значению байта, т.е. (0, 1, 2, 3, …, 255). В процессе обработки данных этот список изменяется. По мере поступления очередного символа на выход подается номер элемента, содержащего его значение. После чего этот символ перемещается в начало списка, смещая остальные элементы вправо.&lt;br /&gt;
&lt;br /&gt;
Современные алгоритмы (например, [http://ru.wikipedia.org/wiki/Bzip2 bzip2]) перед алгоритмом MTF используют [[преобразование Барроуза-Уиллера|алгоритм BWT]], поэтому в качестве примера рассмотрим строку &amp;lt;tex&amp;gt;\mathtt{S} = &amp;lt;/tex&amp;gt;''&amp;quot;BCABAAA&amp;quot;'', полученную из строки ''&amp;quot;ABACABA&amp;quot;'' в результате [[Преобразование Барроуза-Уиллера|преобразования Барроуза-Уиллера]]. Первый символ строки &amp;lt;tex&amp;gt;\mathtt{S}&amp;lt;/tex&amp;gt; 'B' является вторым элементом алфавита ''&amp;quot;ABC&amp;quot;'', поэтому на вывод подаётся &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. После перемещения 'B' в начало алфавита тот принимает вид ''&amp;quot;BAC&amp;quot;''. Дальнейшая работа алгоритма показана в таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Список || Вывод&lt;br /&gt;
|-&lt;br /&gt;
| B || A'''B'''C || 1&lt;br /&gt;
|-&lt;br /&gt;
| C || BA'''C''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| A || CB'''A''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| B || AC'''B''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| A || B'''A'''C || 1&lt;br /&gt;
|-&lt;br /&gt;
| A || '''A'''BC || 0&lt;br /&gt;
|-&lt;br /&gt;
| A || '''A'''BC || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Таким образом, результат работы алгоритма: &amp;lt;tex&amp;gt;MTF(\mathtt{S}) = &amp;lt;/tex&amp;gt; ''&amp;quot;1222100&amp;quot;''.    &lt;br /&gt;
&lt;br /&gt;
Данный алгоритм работает за &amp;lt;tex&amp;gt;O(\mathtt{N} \cdot \mathtt{M})&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\mathtt{N}&amp;lt;/tex&amp;gt; {{---}} размер алфавита, &amp;lt;tex&amp;gt;\mathtt{M}&amp;lt;/tex&amp;gt; {{---}} длина строки, что не очень быстро. Этот алгоритм можно реализовать за &amp;lt;tex&amp;gt;O(\mathtt{N}\log(\mathtt{N+M}))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма за O(N log(N+M)) ==&lt;br /&gt;
&lt;br /&gt;
=== Идея ===&lt;br /&gt;
&lt;br /&gt;
Пусть дан алфавит размером &amp;lt;tex&amp;gt;\mathtt{M}&amp;lt;/tex&amp;gt; и строка &amp;lt;tex&amp;gt;\mathtt{S}&amp;lt;/tex&amp;gt; длиной &amp;lt;tex&amp;gt;\mathtt{N}&amp;lt;/tex&amp;gt;. Заведем массив &amp;lt;tex&amp;gt;\mathtt{used}[1..\mathtt{N+M}]&amp;lt;/tex&amp;gt; и последние &amp;lt;tex&amp;gt;\mathtt{M}&amp;lt;/tex&amp;gt; ячеек заполним единицами. Запомним для каждого символа алфавита позицию в нашем массиве. Например, &amp;lt;tex&amp;gt;\mathtt{alphabet}['a'] = \mathtt{N}+1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\mathtt{alphabet}['b'] = \mathtt{N}+2&amp;lt;/tex&amp;gt;, ... , &amp;lt;tex&amp;gt;\mathtt{alphabet}['z'] = \mathtt{N+M}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
При обработке &amp;lt;tex&amp;gt;\mathtt{i}&amp;lt;/tex&amp;gt;-го символа посчитаем и выпишем сумму на отрезке &amp;lt;tex&amp;gt;[1, \mathtt{alphabet}[\mathtt{S}[\mathtt{i}]] - 1]&amp;lt;/tex&amp;gt;, поменяем значения ячеек &amp;lt;tex&amp;gt;\mathtt{used}[\mathtt{N-i}+1]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathtt{used}[\mathtt{alphabet}[\mathtt{S}[\mathtt{i}]]]&amp;lt;/tex&amp;gt; местами, также стоит поменять значение в ячейке &amp;lt;tex&amp;gt;\mathtt{alphabet}[\mathtt{S}[\mathtt{i}]]&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;\mathtt{N-i}+1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Чтобы добиться сложности  алгоритма &amp;lt;tex&amp;gt;O(\mathtt{N}&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt;\log&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt;(\mathtt{N+M}))&amp;lt;/tex&amp;gt; нужно использовать дерево отрезков или подобное.&lt;br /&gt;
&lt;br /&gt;
=== Псевдокод ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''list&amp;lt;int&amp;gt;''' mtf(N):&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' result(N)&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' used(N+M)&lt;br /&gt;
    '''for''' i = 1 '''to''' M                                      &amp;lt;font color=darkgreen&amp;gt;//Заполняем последние M ячеек единицами&amp;lt;/font color=darkgreen&amp;gt; &lt;br /&gt;
       used[i+N] = 1&lt;br /&gt;
    '''for''' i = 1 '''to''' N&lt;br /&gt;
       result.append(sum(1, alphabet[S[i]] - 1))        &amp;lt;font color=darkgreen&amp;gt;//Запоминаем ответ&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
       swap(used[N-i+1], used[alphabet[S[i]]])          &amp;lt;font color=darkgreen&amp;gt;//Меняем значения&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
       alphabet[S[i]] = N-i+1                           &amp;lt;font color=darkgreen&amp;gt;//Изменяем позицию символа в массиве&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
    '''return''' result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Обратное преобразование ==&lt;br /&gt;
&lt;br /&gt;
Пусть даны строка &amp;lt;tex&amp;gt;\mathtt{s} = &amp;lt;/tex&amp;gt;''&amp;quot;1222100&amp;quot;'' и исходный алфавит ''&amp;quot;ABC&amp;quot;''. Символ с номером &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; в алфавите {{---}} это 'B'. На вывод подаётся 'B', и этот символ перемещается в начало алфавита. Символ с номером &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; в алфавите {{---}} это 'A', поэтому 'A' подается на вывод и перемещается в начало алфавита. Дальнейшее преобразование происходит аналогично.&lt;br /&gt;
&lt;br /&gt;
{| class =&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Список || Вывод&lt;br /&gt;
|-&lt;br /&gt;
| 1 || A'''B'''C || B&lt;br /&gt;
|-&lt;br /&gt;
| 2 || BA'''C''' || C&lt;br /&gt;
|-&lt;br /&gt;
| 2 || CB'''A''' || A&lt;br /&gt;
|-&lt;br /&gt;
| 2 || AC'''B''' || B&lt;br /&gt;
|-&lt;br /&gt;
| 1 || B'''A'''C || A&lt;br /&gt;
|-&lt;br /&gt;
| 0 || '''A'''BC || A&lt;br /&gt;
|-&lt;br /&gt;
| 0 || '''A'''BC || A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Значит, исходная строка &amp;lt;tex&amp;gt;MTF^{-1}(\mathtt{S}) = &amp;lt;/tex&amp;gt;''&amp;quot;BCABAAA&amp;quot;''.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
&lt;br /&gt;
Этот метод позволяет легко преобразовать данные, насыщенные длинными повторами разных символов в блок данных, самыми частыми символами которого будут нули. Без MTF нас подстерегают разного рода трудности в решении проблемы адаптации к данным, поскольку в разных местах данных, полученных на выходе [[Преобразование Барроуза-Уиллера|BWT-преобразования]], разные символы являются преобладающими. Зачастую мы встречаемся с последовательностями типа &amp;quot;bbbbbcccccdddddaaaaa&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Попробуем сжать эту последовательность при помощи, например, [[Алгоритм Хаффмана|метода Хаффмана]]. Вероятности всех четырех символов в данном примере равны &amp;lt;tex&amp;gt;1/4&amp;lt;/tex&amp;gt;. Легко посчитать, что в результате кодирования мы получим последовательность длиной &amp;lt;tex&amp;gt;20\cdot2 = 40&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Теперь проделаем то же самое со строкой, подвергнутой MTF-преобразованию (предположим, начальный алфавит выглядит как ''&amp;quot;abcd&amp;quot;''). &lt;br /&gt;
&lt;br /&gt;
''&amp;quot;bbbbbcccccdddddaaaaa&amp;quot;'' {{---}} исходная строка&lt;br /&gt;
&lt;br /&gt;
''&amp;quot;10000200003000030000&amp;quot;'' {{---}} строка после MTF &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Частота || Вероятность || Код Хаффмана&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 16 || 4/5 || 0&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 2 || 1/10 || 10&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 1 || 1/20 || 110&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 1 || 1/20 || 111&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
В результате сжатия получаем последовательность длиной &amp;lt;tex&amp;gt;16\cdot1 + 2\cdot2 + 3\cdot2 = 26&amp;lt;/tex&amp;gt; бит. Стоит заметить, что выигрыш от применения [[Арифметическое кодирование|арифметического кодирования]] для данного примера будет еще значительней.&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
&lt;br /&gt;
* [http://compression.ru/arctest/descript/bwt-faq.htm Burrows Wheeler Transform FAQ]&lt;br /&gt;
&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Move-To-Front Move-To-Front (Википедия)]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы сжатия ]]&lt;/div&gt;</summary>
		<author><name>Gamezovladislav</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_MTF&amp;diff=44556</id>
		<title>Преобразование MTF</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_MTF&amp;diff=44556"/>
				<updated>2015-01-15T12:18:56Z</updated>
		
		<summary type="html">&lt;p&gt;Gamezovladislav: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Преобразование MTF''' (англ. ''move-to-front'', движение к началу) {{---}} алгоритм кодирования, используемый для предварительной обработки данных (обычно потока байтов) перед сжатием, разработанный для улучшения эффективности последующего кодирования.&lt;br /&gt;
}}&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Изначально каждое возможное значение байта записывается в список (алфавит), в ячейку с номером, равным значению байта, т.е. (0, 1, 2, 3, …, 255). В процессе обработки данных этот список изменяется. По мере поступления очередного символа на выход подается номер элемента, содержащего его значение. После чего этот символ перемещается в начало списка, смещая остальные элементы вправо.&lt;br /&gt;
&lt;br /&gt;
Современные алгоритмы (например, [http://ru.wikipedia.org/wiki/Bzip2 bzip2]) перед алгоритмом MTF используют [[преобразование Барроуза-Уиллера|алгоритм BWT]], поэтому в качестве примера рассмотрим строку &amp;lt;tex&amp;gt;s = &amp;lt;/tex&amp;gt;''&amp;quot;BCABAAA&amp;quot;'', полученную из строки ''&amp;quot;ABACABA&amp;quot;'' в результате [[Преобразование Барроуза-Уиллера|преобразования Барроуза-Уиллера]]. Первый символ строки &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; 'B' является вторым элементом алфавита ''&amp;quot;ABC&amp;quot;'', поэтому на вывод подаётся 1. После перемещения 'B' в начало алфавита тот принимает вид ''&amp;quot;BAC&amp;quot;''. Дальнейшая работа алгоритма показана в таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Список || Вывод&lt;br /&gt;
|-&lt;br /&gt;
| B || A'''B'''C || 1&lt;br /&gt;
|-&lt;br /&gt;
| C || BA'''C''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| A || CB'''A''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| B || AC'''B''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| A || B'''A'''C || 1&lt;br /&gt;
|-&lt;br /&gt;
| A || '''A'''BC || 0&lt;br /&gt;
|-&lt;br /&gt;
| A || '''A'''BC || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Таким образом, результат работы алгоритма: &amp;lt;tex&amp;gt;MTF(s) = &amp;lt;/tex&amp;gt; ''&amp;quot;1222100&amp;quot;''.    &lt;br /&gt;
&lt;br /&gt;
Данный алгоритм работает за &amp;lt;tex&amp;gt;O(N \cdot M)&amp;lt;/tex&amp;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;O(N&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt;\log&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt;M)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма за O(N log(N+M)) ==&lt;br /&gt;
&lt;br /&gt;
=== Идея ===&lt;br /&gt;
&lt;br /&gt;
Пусть дан алфавит размером &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; и строка &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; длиной &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt;. Заведем массив &amp;lt;tex&amp;gt;used[1..N+M]&amp;lt;/tex&amp;gt; и последние &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; ячеек заполним единицами. Запомним для каждого символа алфавита позицию в нашем массиве. Например, &amp;lt;tex&amp;gt;alphabet['a'] = N+1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;alphabet['b'] = N+2&amp;lt;/tex&amp;gt;, ... , &amp;lt;tex&amp;gt;alphabet['z'] = N+M&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
При обработке &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-го символа посчитаем и выпишем сумму на отрезке &amp;lt;tex&amp;gt;[1, alphabet[S[i]] - 1]&amp;lt;/tex&amp;gt;, поменяем значения ячеек &amp;lt;tex&amp;gt;used[N-i+1]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;used[alphabet[S[i]]]&amp;lt;/tex&amp;gt; местами, также стоит поменять значение в ячейке &amp;lt;tex&amp;gt;alphabet[S[i]]&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;N-i+1&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;\log&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt;(N+M))&amp;lt;/tex&amp;gt; нужно использовать дерево отрезков или подобное.&lt;br /&gt;
&lt;br /&gt;
=== Псевдокод ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''list&amp;lt;int&amp;gt;''' mtf(N):&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' result(N)&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' used(N+M)&lt;br /&gt;
    '''for''' i = 1 '''to''' M                                      &amp;lt;font color=darkgreen&amp;gt;//Заполняем последние M ячеек единицами&amp;lt;/font color=darkgreen&amp;gt; &lt;br /&gt;
       used[i+N] = 1&lt;br /&gt;
    '''for''' i = 1 '''to''' N&lt;br /&gt;
       result.append(sum(1, alphabet[S[i]] - 1))        &amp;lt;font color=darkgreen&amp;gt;//Запоминаем ответ&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
       swap(used[N-i+1], used[alphabet[S[i]]])          &amp;lt;font color=darkgreen&amp;gt;//Меняем значения&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
       alphabet[S[i]] = N-i+1                           &amp;lt;font color=darkgreen&amp;gt;//Изменяем позицию символа в массиве&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
    '''return''' result&lt;br /&gt;
&amp;lt;/code&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;quot;1222100&amp;quot;'' и исходный алфавит ''&amp;quot;ABC&amp;quot;''. Символ с номером 1 в алфавите {{---}} это 'B'. На вывод подаётся 'B', и этот символ перемещается в начало алфавита. Символ с номером 2 в алфавите {{---}} это 'A', поэтому 'A' подается на вывод и перемещается в начало алфавита. Дальнейшее преобразование происходит аналогично.&lt;br /&gt;
&lt;br /&gt;
{| class =&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Список || Вывод&lt;br /&gt;
|-&lt;br /&gt;
| 1 || A'''B'''C || B&lt;br /&gt;
|-&lt;br /&gt;
| 2 || BA'''C''' || C&lt;br /&gt;
|-&lt;br /&gt;
| 2 || CB'''A''' || A&lt;br /&gt;
|-&lt;br /&gt;
| 2 || AC'''B''' || B&lt;br /&gt;
|-&lt;br /&gt;
| 1 || B'''A'''C || A&lt;br /&gt;
|-&lt;br /&gt;
| 0 || '''A'''BC || A&lt;br /&gt;
|-&lt;br /&gt;
| 0 || '''A'''BC || A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Значит, исходная строка &amp;lt;tex&amp;gt;MTF^{-1}(s) = &amp;lt;/tex&amp;gt;''&amp;quot;BCABAAA&amp;quot;''.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
&lt;br /&gt;
Этот метод позволяет легко преобразовать данные, насыщенные длинными повторами разных символов в блок данных, самыми частыми символами которого будут нули. Без MTF нас подстерегают разного рода трудности в решении проблемы адаптации к данным, поскольку в разных местах данных, полученных на выходе [[Преобразование Барроуза-Уиллера|BWT-преобразования]], разные символы являются преобладающими. Зачастую мы встречаемся с последовательностями типа &amp;quot;bbbbbcccccdddddaaaaa&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Попробуем сжать эту последовательность при помощи, например, [[Алгоритм Хаффмана|метода Хаффмана]]. Вероятности всех четырех символов в данном примере равны 1/4. Легко посчитать, что в результате кодирования мы получим последовательность длиной &amp;lt;tex&amp;gt;20\cdot2 = 40&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Теперь проделаем то же самое со строкой, подвергнутой MTF-преобразованию (предположим, начальный алфавит выглядит как ''&amp;quot;abcd&amp;quot;''). &lt;br /&gt;
&lt;br /&gt;
''&amp;quot;bbbbbcccccdddddaaaaa&amp;quot;'' {{---}} исходная строка&lt;br /&gt;
&lt;br /&gt;
''&amp;quot;10000200003000030000&amp;quot;'' {{---}} строка после MTF &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Частота || Вероятность || Код Хаффмана&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 16 || 4/5 || 0&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 2 || 1/10 || 10&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 1 || 1/20 || 110&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 1 || 1/20 || 111&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
В результате сжатия получаем последовательность длиной &amp;lt;tex&amp;gt;16\cdot1 + 2\cdot2 + 3\cdot2 = 26&amp;lt;/tex&amp;gt; бит. Стоит заметить, что выигрыш от применения [[Арифметическое кодирование|арифметического кодирования]] для данного примера будет еще значительней.&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
&lt;br /&gt;
* [http://compression.ru/arctest/descript/bwt-faq.htm Burrows Wheeler Transform FAQ]&lt;br /&gt;
&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Move-To-Front Move-To-Front (Википедия)]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы сжатия ]]&lt;/div&gt;</summary>
		<author><name>Gamezovladislav</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_MTF&amp;diff=44555</id>
		<title>Преобразование MTF</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_MTF&amp;diff=44555"/>
				<updated>2015-01-15T11:39:05Z</updated>
		
		<summary type="html">&lt;p&gt;Gamezovladislav: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Преобразование MTF''' (''move-to-front'', движение к началу) {{---}} алгоритм кодирования, используемый для предварительной обработки данных (обычно потока байтов) перед сжатием, разработанный для улучшения эффективности последующего кодирования.&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Изначально каждое возможное значение байта записывается в список (алфавит), в ячейку с номером, равным значению байта, т.е. (0, 1, 2, 3, …, 255). В процессе обработки данных этот список изменяется. По мере поступления очередного символа на выход подается номер элемента, содержащего его значение. После чего этот символ перемещается в начало списка, смещая остальные элементы вправо.&lt;br /&gt;
&lt;br /&gt;
Современные алгоритмы (например, [http://ru.wikipedia.org/wiki/Bzip2 bzip2]) перед алгоритмом MTF используют [[преобразование Барроуза-Уиллера|алгоритм BWT]], поэтому в качестве примера рассмотрим строку &amp;lt;tex&amp;gt;s = &amp;lt;/tex&amp;gt;''&amp;quot;BCABAAA&amp;quot;'', полученную из строки ''&amp;quot;ABACABA&amp;quot;'' в результате [[Преобразование Барроуза-Уиллера|преобразования Барроуза-Уиллера]]. Первый символ строки &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; 'B' является вторым элементом алфавита ''&amp;quot;ABC&amp;quot;'', поэтому на вывод подаётся 1. После перемещения 'B' в начало алфавита тот принимает вид ''&amp;quot;BAC&amp;quot;''. Дальнейшая работа алгоритма показана в таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Список || Вывод&lt;br /&gt;
|-&lt;br /&gt;
| B || A'''B'''C || 1&lt;br /&gt;
|-&lt;br /&gt;
| C || BA'''C''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| A || CB'''A''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| B || AC'''B''' || 2&lt;br /&gt;
|-&lt;br /&gt;
| A || B'''A'''C || 1&lt;br /&gt;
|-&lt;br /&gt;
| A || '''A'''BC || 0&lt;br /&gt;
|-&lt;br /&gt;
| A || '''A'''BC || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Таким образом, результат работы алгоритма: &amp;lt;tex&amp;gt;MTF(s) = &amp;lt;/tex&amp;gt; ''&amp;quot;1222100&amp;quot;''.    &lt;br /&gt;
&lt;br /&gt;
Данный алгоритм работает за &amp;lt;tex&amp;gt;O(N \cdot M)&amp;lt;/tex&amp;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;O(N&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt;\log&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt;M)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма за O(Nlog(N+M)) ==&lt;br /&gt;
&lt;br /&gt;
=== Идея ===&lt;br /&gt;
&lt;br /&gt;
Пусть дан алфавит размером &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; и строка &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; длиной &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt;. Заведем массив &amp;lt;tex&amp;gt;used[1..N+M]&amp;lt;/tex&amp;gt; и последние &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; ячеек заполним единицами. Запомним для каждого символа алфавита позицию в нашем массиве. Например, &amp;lt;tex&amp;gt;alphabet['a'] = N+1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;alphabet['b'] = N+2&amp;lt;/tex&amp;gt;, ... , &amp;lt;tex&amp;gt;alphabet['z'] = N+M&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
При обработке &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-го символа посчитаем и выпишем сумму на отрезке &amp;lt;tex&amp;gt;[1, alphabet[S[i]] - 1]&amp;lt;/tex&amp;gt;, поменяем значения ячеек &amp;lt;tex&amp;gt;used[N-i+1]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;used[alphabet[S[i]]]&amp;lt;/tex&amp;gt; местами, также стоит поменять значение в ячейке &amp;lt;tex&amp;gt;alphabet[S[i]]&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;N-i+1&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;\log&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt;(N+M))&amp;lt;/tex&amp;gt; нужно использовать дерево отрезков или подобное.&lt;br /&gt;
&lt;br /&gt;
=== Псевдокод ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''list&amp;lt;int&amp;gt;''' mtf(N):&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' result(N)&lt;br /&gt;
    '''list&amp;lt;int&amp;gt;''' used(N+M)&lt;br /&gt;
    '''for''' i = 1 '''to''' M                                      &amp;lt;font color=darkgreen&amp;gt;//Заполняем последние N ячеек единицами&amp;lt;/font color=darkgreen&amp;gt; &lt;br /&gt;
       used[i+N] = 1&lt;br /&gt;
    '''for''' i = 1 '''to''' N&lt;br /&gt;
       result.append(sum(1, alphabet[S[i]] - 1))        &amp;lt;font color=darkgreen&amp;gt;//Запоминаем ответ&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
       swap(used[N-i+1], used[alphabet[S[i]]])          &amp;lt;font color=darkgreen&amp;gt;//Меняем значения&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
       alphabet[S[i]] = N-i+1                           &amp;lt;font color=darkgreen&amp;gt;//Изменяем позицию символа в массиве&amp;lt;/font color=darkgreen&amp;gt;&lt;br /&gt;
    '''return''' result&lt;br /&gt;
&amp;lt;/code&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;quot;1222100&amp;quot;'' и исходный алфавит ''&amp;quot;ABC&amp;quot;''. Символ с номером 1 в алфавите {{---}} это 'B'. На вывод подаётся 'B', и этот символ перемещается в начало алфавита. Символ с номером 2 в алфавите {{---}} это 'A', поэтому 'A' подается на вывод и перемещается в начало алфавита. Дальнейшее преобразование происходит аналогично.&lt;br /&gt;
&lt;br /&gt;
{| class =&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Список || Вывод&lt;br /&gt;
|-&lt;br /&gt;
| 1 || A'''B'''C || B&lt;br /&gt;
|-&lt;br /&gt;
| 2 || BA'''C''' || C&lt;br /&gt;
|-&lt;br /&gt;
| 2 || CB'''A''' || A&lt;br /&gt;
|-&lt;br /&gt;
| 2 || AC'''B''' || B&lt;br /&gt;
|-&lt;br /&gt;
| 1 || B'''A'''C || A&lt;br /&gt;
|-&lt;br /&gt;
| 0 || '''A'''BC || A&lt;br /&gt;
|-&lt;br /&gt;
| 0 || '''A'''BC || A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Значит, исходная строка &amp;lt;tex&amp;gt;MTF^{-1}(s) = &amp;lt;/tex&amp;gt;''&amp;quot;BCABAAA&amp;quot;''.&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
&lt;br /&gt;
Этот метод позволяет легко преобразовать данные, насыщенные длинными повторами разных символов в блок данных, самыми частыми символами которого будут нули. Без MTF нас подстерегают разного рода трудности в решении проблемы адаптации к данным, поскольку в разных местах данных, полученных на выходе [[Преобразование Барроуза-Уиллера|BWT-преобразования]], разные символы являются преобладающими. Зачастую мы встречаемся с последовательностями типа &amp;quot;bbbbbcccccdddddaaaaa&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Попробуем сжать эту последовательность при помощи, например, [[Алгоритм Хаффмана|метода Хаффмана]]. Вероятности всех четырех символов в данном примере равны 1/4. Легко посчитать, что в результате кодирования мы получим последовательность длиной &amp;lt;tex&amp;gt;20\cdot2 = 40&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Теперь проделаем то же самое со строкой, подвергнутой MTF-преобразованию (предположим, начальный алфавит выглядит как ''&amp;quot;abcd&amp;quot;''). &lt;br /&gt;
&lt;br /&gt;
''&amp;quot;bbbbbcccccdddddaaaaa&amp;quot;'' {{---}} исходная строка&lt;br /&gt;
&lt;br /&gt;
''&amp;quot;10000200003000030000&amp;quot;'' {{---}} строка после MTF &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Символ || Частота || Вероятность || Код Хаффмана&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 16 || 4/5 || 0&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 2 || 1/10 || 10&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 1 || 1/20 || 110&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 1 || 1/20 || 111&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
В результате сжатия получаем последовательность длиной &amp;lt;tex&amp;gt;16\cdot1 + 2\cdot2 + 3\cdot2 = 26&amp;lt;/tex&amp;gt; бит. Стоит заметить, что выигрыш от применения [[Арифметическое кодирование|арифметического кодирования]] для данного примера будет еще значительней.&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
&lt;br /&gt;
* [http://compression.ru/arctest/descript/bwt-faq.htm Burrows Wheeler Transform FAQ]&lt;br /&gt;
&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Move-To-Front Move-To-Front (Википедия)]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы сжатия ]]&lt;/div&gt;</summary>
		<author><name>Gamezovladislav</name></author>	</entry>

	</feed>