Изменения

Перейти к: навигация, поиск

Преобразование MTF

2341 байт добавлено, 14:39, 15 января 2015
Нет описания правки
'''Преобразование MTF''' (''move-to-front'', движение к началу) {{---}} алгоритм кодирования, используемый для предварительной обработки данных (обычно потока байтов) перед сжатием, разработанный для улучшения эффективности последующего кодирования.
== Описание алгортима алгоритма ==
Изначально каждое возможное значение байта записывается в список (алфавит), в ячейку с номером, равным значению байта, т.е. (0, 1, 2, 3, …, 255). В процессе обработки данных этот список изменяется. По мере поступления очередного символа на выход подается номер элемента, содержащего его значение. После чего этот символ перемещается в начало списка, смещая остальные элементы вправо.
|}
Таким образом, результат работы алгоритма: <tex>MTF(s) = </tex> ''"1222100"''.
Данный алгоритм работает за <tex>O(N \cdot M)</tex>, где <tex>N</tex> {{---}} размер алфавита, <tex>M</tex> {{---}} длина строки, что не очень быстро. Этот алгоритм можно реализовать за <tex>O(N</tex><tex>\log</tex><tex>M)</tex>.
 
== Описание алгоритма за O(Nlog(N+M)) ==
 
=== Идея ===
 
Пусть дан алфавит размером <tex>M</tex> и строка <tex>S</tex> длиной <tex>N</tex>. Заведем массив <tex>used[1..N+M]</tex> и последние <tex>M</tex> ячеек заполним единицами. Запомним для каждого символа алфавита позицию в нашем массиве. Например, <tex>alphabet['a'] = N+1</tex>, <tex>alphabet['b'] = N+2</tex>, ... , <tex>alphabet['z'] = N+M</tex>.
 
При обработке <tex>i</tex>-го символа посчитаем и выпишем сумму на отрезке <tex>[1, alphabet[S[i]] - 1]</tex>, поменяем значения ячеек <tex>used[N-i+1]</tex> и <tex>used[alphabet[S[i]]]</tex> местами, также стоит поменять значение в ячейке <tex>alphabet[S[i]]</tex> на <tex>N-i+1</tex>.
 
Чтобы добиться сложности алгоритма <tex>O(N</tex><tex>\log</tex><tex>(N+M))</tex> нужно использовать дерево отрезков или подобное.
 
=== Псевдокод ===
 
<code>
'''list<int>''' mtf(N):
'''list<int>''' result(N)
'''list<int>''' used(N+M)
'''for''' i = 1 '''to''' M <font color=darkgreen>//Заполняем последние N ячеек единицами</font color=darkgreen>
used[i+N] = 1
'''for''' i = 1 '''to''' N
result.append(sum(1, alphabet[S[i]] - 1)) <font color=darkgreen>//Запоминаем ответ</font color=darkgreen>
swap(used[N-i+1], used[alphabet[S[i]]]) <font color=darkgreen>//Меняем значения</font color=darkgreen>
alphabet[S[i]] = N-i+1 <font color=darkgreen>//Изменяем позицию символа в массиве</font color=darkgreen>
'''return''' result
</code>
== Обратное преобразование ==
Пусть даны строка <tex>s = </tex>''"1222100"'' и исходный алфавит ''"ABC"''. Символ с номером 1 в алфавите {{---}} это 'B'. На вывод подаётся 'B', и этот символ перемещается в начало алфавита. Символ с номером 2 в алфавите {{---}} это 'A', поэтому 'A' подается на вывод и перемещается в начало алфавита. Дальнейшее преобразование происходит аналогично.
{| class="wikitable"
! Символ || Список || Вывод
|-
10
правок

Навигация