Изменения

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

Алгоритм LZW

7679 байт добавлено, 19:17, 4 сентября 2022
м
rollbackEdits.php mass rollback
'''Алгори́тм Ле́мпеля — Зи́ва — Ве́лча''' ('''Lempel-Ziv-Welch''', '''Непосредственным предшественником LZW''') — это универсальный является [[Алгоритмы LZ77 и LZ78|алгоритм сжатия данных без потерьLZ78]], созданный опубликованный Абрахамом Лемпелем(''Abraham Lempel''), и Якобом Зивом (''Jacob Ziv'') и в 1978 г. Этот алгоритм воспринимался как математическая абстракция до 1984 г., когда Терри Велчем Уэлч (''Terry A. Welch''). Он был опубликован Велчем в 1984 годуопубликовал свою работу с модифицированным алгоритмом, получившим в качестве улучшенной реализации [[Алгоритм LZ78|алгоритма LZ78]], опубликованного Лемпелем и Зивом в 1978 году.Алгоритм разработан так, чтобы его можно было быстро реализовать, но он не обязательно оптимален, поскольку он не проводит никакого анализа входных данныхдальнейшем название LZW (''Lempel{{---}}Ziv{{---}}Welch'').
== Применение ==
На момент своего появления алгоритм Опубликование алгоритма LZW давал лучший коэффициент сжатия, для большинства произвело большое впечатление на всех специалистов по сжатию информации. За этим последовало большое количество программ и приложений, чем любой другой хорошо известный метод того времени. Он стал первым широко используемым на компьютерах методом сжатия данныхс различными вариантами этого метода.
Алгоритм был реализован в программе compressЭтот метод позволяет достичь одну из наилучших степеней сжатия среди других существующих методов сжатия графических данных, которая стала более при полном отсутствии потерь или менее стандартной утилитой Unix-систем приблизительно искажений в 1986 годуисходных файлах. Несколько В настоящее время используется в файлах формата TIFF, PDF, GIF, PostScript и других , а также отчасти во многих популярных утилит-архиваторов также используют этот метод или близкие к немупрограммах сжатия данных (ZIP, ARJ, LHA).
В 1987 году алгоритм стал частью стандарта на формат изображений GIF. Он также может (опционально) использоваться в формате TIFF.== Описание ==
В настоящее времяПроцесс сжатия выглядит следующим образом: последовательно считываются символы входного потока и происходит проверка, алгоритм содержится существует ли в стандарте PDFсозданной таблице строк такая строка. Если такая строка существует, считывается следующий символ, а если строка не существует, в поток заносится код для предыдущей найденной строки, строка заносится в таблицу, а поиск начинается снова.
== Описание ==Например, если сжимают байтовые данные (текст), то строк в таблице окажется <tex>256</tex> (от <tex>"0"</tex> до <tex>"255"</tex>). Если используется <tex>10</tex>-битный код, то под коды для строк остаются значения в диапазоне от <tex>256</tex> до <tex>1023</tex>. Новые строки формируют таблицу последовательно, т. е. можно считать индекс строки ее кодом.
Данный Для декодирования на вход подается только закодированный текст, поскольку алгоритм при сжатии (кодировании) динамически создаёт LZW может воссоздать соответствующую таблицу преобразования строк: определённым последовательностям символов (словам) ставятся в соответствие группы бит фиксированной длины (обычно 12-битные)непосредственно по закодированному тексту. Таблица инициализируется всеми 1-символьными строками (Алгоритм генерирует однозначно декодируемый код за счет того, что каждый раз, когда генерируется новый код, новая строка добавляется в случае 8-битных символов — это 256 записей)таблицу строк. По мере кодированияLZW постоянно проверяет, алгоритм просматривает текст символ за символомявляется ли строка уже известной, и сохраняет каждую новую, уникальную 2-символьную строку в таблицу в виде пары код/символесли так, где выводит существующий код ссылается на соответствующий первый символбез генерации нового. После того как новая 2-символьная Таким образом, каждая строка сохранена будет храниться в таблице, на выход передаётся код первого символаединственном экземпляре и иметь свой уникальный номер. Когда на входе читается очередной символСледовательно, для него по таблице находится уже встречавшаяся при декодировании во время получения нового кода генерируется новая строка максимальной длины, после чего в таблице сохраняется код этой строки со следующим символом на входе; на выход выдаётся код этой строкиа при получении уже известного, а следующий символ используется в качестве начала следующей строкистрока извлекается из словаря.
Алгоритму декодирования на входе требуется только закодированный текст, поскольку он может воссоздать соответствующую таблицу преобразования непосредственно по закодированному тексту.== Алгоритм ==
== Алгоритм =Кодирование ===* Начало.* ''' Шаг 1. ''' Все возможные символы заносятся в словарь. Во входную фразу <tex>X</tex> заносится первый символ сообщения.* ''' Шаг 2. ''' Считать очередной символ <tex>Y</tex> из сообщения.* ''' Шаг 3. ''' Если <tex>Y</tex> {{---}} это символ конца сообщения, то выдать код для <tex>X</tex>, иначе: ** Если фраза <tex>XY</tex> уже имеется в словаре, то присвоить входной фразе значение <tex>XY</tex> и перейти к ''' Шагу 2 ''', ** Иначе выдать код для входной фразы <tex>X</tex>, добавить <tex>XY</tex> в словарь и присвоить входной фразе значение <tex>Y</tex>. Перейти к ''' Шагу 2. '''* Конец.
# Инициализация словаря всеми возможными односимвольными фразами=== Декодирование ===* Начало. Инициализация входной фразы ω первым символом * ''' Шаг 1. ''' Все возможные символы заносятся в словарь. Во входную фразу <tex>X</tex> заносится первый код декодируемого сообщения.# * ''' Шаг 2. ''' Считать очередной символ K код <tex>Y</tex> из кодируемого сообщения.# * ''' Шаг 3. ''' Если КОНЕЦ_СООБЩЕНИЯ<tex>Y</tex> {{---}} это конец сообщения, то выдать код для ωсимвол, соответствующий коду <tex>X</tex>, иначе: # ** Если фраза ωK уже есть фразы под кодом <tex>XY</tex> нет в словаре, присвоить входной фразе значение ωK и перейти к Шагу 2вывести фразу, иначе выдать код ωсоответствующую коду <tex>X</tex>, добавить ωK а фразу с кодом <tex>XY</tex> занести в словарь, . ** Иначе присвоить входной фразе значение K код <tex>XY</tex> и перейти к ''' Шагу 2'''.* Конец.
== Пример ==
Данный Рассмотрим пример показывает алгоритм LZW в действии, показывая состояние выходных данных сжатия и словаря на каждой стадии, как при кодировании, так и при раскодировании декодирования сообщения. С тем чтобы сделать изложение проще, мы ограничимся простым алфавитом — только заглавные буквы, без знаков препинания и пробеловСначала создадим начальный словарь единичных символов.СообщениеВ стандартной кодировке ASCII имеется <tex>256</tex> различных символов, которое нужно сжатьпоэтому, выглядит следующим образом: TOBEORNOTTOBEORTOBEORNOT#Маркер '''#''' используется для обозначения конца сообщения. Тем самымтого, чтобы все они были корректно закодированы (если нам неизвестно, какие символы будут присутствовать в нашем алфавите 27 символов (26 заглавных букв от A до Z и #исходном файле, а какие — нет), начальный размер кода будет равен <tex>8</tex> битам. Компьютер представляет это Если нам заранее известно, что в виде групп исходном файле будет меньшее количество различных символов, то вполне разумно уменьшить количество бит, для представления каждого символа алфавита нам достаточно группы из 5 бит на символ. По мере роста словаряЧтобы инициализировать таблицу, размер групп должен растимы установим соответствие кода <tex>0</tex> соответствующему символу с битовым кодом <tex>00000000</tex>, тогда <tex>1</tex>соответствует символу с тем чтобы учесть новые элементы. 5-битные группы дают 2кодом <suptex>500000001</suptex> = 32 возможных комбинации бит, поэтому, когда в словаре появится 33-е слово, алгоритм должен перейти к 6-битным группами т.д. Заметим, что, поскольку используется группа из всех нолей 00000, то 33-я группа имеет код '''32'''до кода <tex>255</tex>. Начальный словарь будет содержать: {| class="wikitable" border = 1, style="float:right; text-align: right; margin-left: auto; margin-right: auto;"
|- bgcolor=#EEEEEE
! Символ !! Битовый код !! Номер|-| # || 00000 || 0|-| A || 00001 || 1|-| B || 00010 || 2|-| C || 00011 || 3|-| D || 00100 || 4|-| E || 00101 || 5|-| F || 00110 || 6|-| G || 00111 || 7|-| H || 01000 || 8|-| I || 01001 || 9|-| J || 01010 || 10|-| K || 01011 || 11|-| L || 01100 || 12|-| M || 01101 || 13|-| N || 01110 || 14|-| O || 01111 || 15|-| P || 10000 || 16|-| Q || 10001 || 17Код
|-
| R a || 10010 000 || 180
|-
| S b || 10011 001 || 191
|-
| T c || 10100 010 || 202
|-
| U d || 10101 011 || 21|-| V || 10110 || 22|-| W || 10111 || 23|-| X || 11000 || 24|-| Y || 11001 || 25|-| Z || 11010 || 263
|-
| e || 100 || 4
|}
 
Больше в таблице не будет других кодов, обладающих этим свойством.<br>
По мере роста словаря, размер групп должен расти, с тем чтобы учесть новые элементы. <tex>8</tex>-битные группы дают <tex>256</tex> возможных комбинации бит, поэтому, когда в словаре появится <tex>256</tex>-е слово, алгоритм должен перейти к <tex>9</tex>-битным группам. При появлении <tex>512</tex>-ого слова произойдет переход к <tex>10</tex>-битным группам, что дает возможность запоминать уже <tex>1024</tex> слова и т.д.
 
В нашем примере алгоритму заранее известно о том, что будет использоваться всего <tex>5</tex> различных символов, следовательно, для их хранения будет использоваться минимальное количество бит, позволяющее нам их запомнить, то есть <tex>3</tex> (<tex>8</tex> различных комбинаций).
=== Кодирование ===
Без использования алгоритма LZWПусть мы сжимаем последовательность <tex>abacabadabacabae</tex>. * '''Шаг 1: '''Тогда, согласно изложенному выше алгоритму, мы добавим к изначально пустой строке <tex>a</tex> и проверим, есть ли строка <tex>a</tex> в таблице. Поскольку мы при передаче сообщения как оно есть — 25 символов по инициализации занесли в таблицу все строки из одного символа, то строка <tex>a</tex> есть в таблице. * '''Шаг 2: '''Далее мы читаем следующий символ <tex>b</tex> из входного потока и проверяем, есть ли строка <tex>ab</tex> в таблице. Такой строки в таблице пока нет.Добавляем в таблицу <tex>\langle5\rangle</tex> <tex>ab</tex>. В поток: <tex>\langle0\rangle</tex>;* '''Шаг 3: '''<tex>ba</tex> — нет. В таблицу: <tex>\langle6\rangle</tex> <tex>ba</tex>. В поток: <tex>\langle1\rangle</tex>;* '''Шаг 4: '''<tex>ac</tex> — нет. В таблицу: <tex>\langle7\rangle</tex> <tex>ac</tex>. В поток: <tex>\langle0\rangle</tex>;* '''Шаг 5 бит на каждый — оно займёт 125 бит: '''<tex>ca</tex> — нет. В таблицу: <tex>\langle8\rangle</tex> <tex>ca</tex>. В поток: <tex>\langle2\rangle</tex>;* '''Шаг 6: '''<tex>ab</tex> — есть в таблице; <tex>aba</tex> — нет. В таблицу: <tex>\langle9\rangle</tex> <tex>aba</tex>. Сравним это с темВ поток: <tex>\langle5\rangle</tex>;* '''Шаг 7: '''<tex>ad</tex> — нет. В таблицу: <tex>\langle10\rangle</tex> <tex>ad</tex>. В поток: <tex>\langle0\rangle</tex>;* '''Шаг 8: '''<tex>da</tex> — нет. В таблицу: <tex>\langle11\rangle</tex> <tex>da</tex>. В поток: <tex>\langle3\rangle</tex>;* '''Шаг 9: '''<tex>aba</tex> — есть в таблице; <tex>abac</tex> — нет. В таблицу: <tex>\langle12\rangle</tex> <tex>abac</tex>. В поток: <tex>\langle9\rangle</tex>;* '''Шаг 10: '''<tex>ca</tex> — есть в таблице; <tex>cab</tex> — нет. В таблицу: <tex>\langle13\rangle</tex> <tex>cab</tex>. В поток: <tex>\langle8\rangle</tex>;* '''Шаг 11: '''<tex>ba</tex> — есть в таблице; <tex>bae</tex> — нет. В таблицу: <tex>\langle14\rangle</tex> <tex>bae</tex>. В поток: <tex>\langle6\rangle</tex>;* '''Шаг 12: '''И, наконец последняя строка <tex>e</tex>, за ней идет конец сообщения, что получается при использовании LZW:поэтому мы просто выводим в поток <tex>\langle4\rangle</tex>.
{| class="wikitable" border =1, style="text-align: center; margin-left: auto; margin-right: auto;"
|- bgcolor =#EEEEEE
! scope="col" width="6em" rowspan="2" | Текущая строка
! scope="col" width="6em" rowspan="2" | Текущий символ
! scope="col" width="4em" rowspan="2" | Следующий символ
! colspan="2" | Вывод
! scope="col" width="7em" rowspan="2" colspan="2" | Расширенный словарь! rowspan="2" | КомментарииСловарь
|- bgcolor =#EEEEEE
! Код || Биты
|-
| style="text-align: center;" | NULL
| style="text-align: center;" | T || ||
| style="border-right: none;" |
| style="border-left: none;" | ||
|-
| style="text-align: center;" | T
| style="text-align: center;" | O
| 20 || 10100
| style="border-right: none;" | 27:
| style="border-left: none;" | TO
| style="text-align: left;" |
|-
| style="text-align: center;" | Oab| style="text-align: center;" | Ba| 15 style="text-align: center;" | b|0 | 01111| 000| style="border-right: none;" | 285:| style="border-left: none;" | OB ||ab
|-
| style="text-align: center;" | Bba| style="text-align: center;" | Eb| 2 style="text-align: center;" | a|1 | 00010| 001| style="border-right: none;" | 296:| style="border-left: none;" | BE ||ba
|-
| style="text-align: center;" | Eac| style="text-align: center;" | Oa| 5 style="text-align: center;" | c|0 | 00101| 000| style="border-right: none;" | 307:| style="border-left: none;" | EO ||ac
|-
| style="text-align: center;" | Oca| style="text-align: center;" | Rc| 15 style="text-align: center;" | a|2 | 01111| 010| style="border-right: none;" | 318:| style="border-left: none;" | OR ||ca
|-
| style="text-align: center;" | Rab| style="text-align: center;" | N| 18 || 10010a| style="bordertext-rightalign: nonecenter;" | 32:b| - || -| style="border-leftright: none;" | RN-| style="textborder-alignleft: leftnone;" | -
|-
| style="text-align: center;" | Naba| style="text-align: center;" | Ob| 14 style="text-align: center;" | a|5 | 001110| 0101| style="border-right: none;" | 339:| style="border-left: none;" | NO || начинаем использовать 6 битовaba
|-
| style="text-align: center;" | Oad| style="text-align: center;" | Ta| 15 style="text-align: center;" | d|0 | 001111| 0000| style="border-right: none;" | 3410:| style="border-left: none;" | OT ||ad
|-
| style="text-align: center;" | Tda| style="text-align: center;" | Td| 20 style="text-align: center;" | a|3 | 010100| 0011| style="border-right: none;" | 3511:| style="border-left: none;" | TT ||da
|-
| style="text-align: center;" | TOab| style="text-align: center;" | Ba| 27 style="text-align: center;" |b| 011011- || -| style="border-right: none;" | 36:-| style="border-left: none;" | TOB ||-
|-
| style="text-align: center;" | BEaba| style="text-align: center;" | Ob| 29 style="text-align: center;" |a| 011101- || -| style="border-right: none;" | 37:-| style="border-left: none;" | BEO ||-
|-
| style="text-align: center;" | ORabac| style="text-align: center;" | Ta| 31 style="text-align: center;" | c|9 | 011111| 1001| style="border-right: none;" | 3812:| style="border-left: none;" | ORT ||abac
|-
| style="text-align: center;" | TOBca| style="text-align: center;" | Ec| 36 style="text-align: center;" |a| 100100- || -| style="border-right: none;" | 39:-| style="border-left: none;" | TOBE ||-
|-
| style="text-align: center;" | EOcab| style="text-align: center;" | Ra| 30 style="text-align: center;" | b|8 | 011110| 1000| style="border-right: none;" | 4013:| style="border-left: none;" | EOR ||cab
|-
| style="text-align: center;" | RNba| style="text-align: center;" | Ob| 32 style="text-align: center;" |a| 100000- || -| style="border-right: none;" | 41:-| style="border-left: none;" | RNO ||-
|-
| style="text-align: center;" | OTbae| style="text-align: center;" | #| 34 || 100010a| style="bordertext-rightalign: nonecenter;" |e| 6 || 0110| style="border-leftright: none;" |14:| style="textborder-alignleft: leftnone;" | # останавливаем алгоритм; выводим текущую последовательностьbae
|-
| style="text-align: center;" |e| style="text-align: center;" || 0 || 000000e| style="bordertext-rightalign: nonecenter;" |-| 4 || 0100| style="border-leftright: none;" |-| style="textborder-alignleft: centernone;" | и останавливаем кодирование-
|-
|}
Длина закодированного текста = 6 × Итак, мы получаем закодированное сообщение <tex>0 1 0 2 5 + 11 × 0 3 9 8 6 4</tex> и его битовый эквивалент <tex>000 001 000 010 0101 0000 0011 1001 1000 0110 0100</tex>. Каждый символ исходного сообщения был закодирован группой из трех бит, сообщение содержало <tex>16</tex> символов, следовательно длина сообщения составляла <tex>3 \cdot 16 = 96 битов48</tex> бит.
Таким образомЗакодированное же сообщение так же сначала кодировалось трехбитными группами, а при появлении в словаре восьмого слова — четырехбитными, итого длина сообщения составила <tex>4 \cdot 3 + 7 \cdot 4 = 40</tex> бит, используя LZW мы сократили сообщение что на 29 <tex>8</tex> бит из 125 — это почти 22 %. Если сообщение будет длиннее, то элементы словаря будут представлять всё более и более длинные части текста, благодаря чему повторяющиеся слова будут представлены очень компактнокороче исходного.
=== Декодирование ===
 Особенность LZW заключается в том, что для декомпрессии нам не надо сохранять таблицу строк в файл для распаковки. Алгоритм построен таким образом, что мы в состоянии восстановить таблицу строк, пользуясь только потоком кодов.  Теперь представим , что мы получили закодированное сообщение, приведённое выше, и нам нужно его декодировать. Прежде всего, нам нужно знать начальный словарь, а последующие записи словаря мы можем реконструировать уже на ходу, поскольку они являются просто конкатенацией предыдущих записей. Кроме того, в процессе кодировании и декодировании коды в словарь добавляются во время обработки одного и того же символа, т.е. это происходит “синхронно”.
! scope="col" width="6em" rowspan="2" | На выходе
! colspan="4" | Новая запись
! rowspan="2" | Комментарии
|- bgcolor = #EEEEEE
! Биты !! Код
! scope="col" width="6em" colspan="2" | Частичная
|-
| 10100 000 || 200| style="text-align: center;" | Ta| style="border-right: none;" |-| style="border-left: none;" | -| style="border-right: none;" | 5:| style="border-left: none;" | a?|-| 001 || 1| style="text-align: center;" | b| style="border-right: none;" | 5:| style="border-left: none;" | ab| style="border-right: none;" | 6:| style="border-left: none;" | b?|-| 000 || 0| style="text-align: center;" | a| style="border-right: none;" | 6:| style="border-left: none;" | ba| style="border-right: none;" | 7:| style="border-left: none;" | a?|-| 010 || 2| style="text-align: center;" | c| style="border-right: none;" | 7:| style="border-left: none;" |ac| style="border-right: none;" | 278:| style="border-left: none;" | Tc? |-| 0101 ||5| style="text-align: center;" | ab| style="border-right: none;" | 8:| style="border-left: none;" | ca| style="border-right: none;" | 9:| style="border-left: none;" | ab?|-| 0000 || 0| style="text-align: center;" | a| style="border-right: none;" | 9:| style="border-left: none;" | aba| style="border-right: none;" | 10:| style="border-left: none;" | a?|-| 0011 || 3| style="text-align: center;" | d| style="border-right: none;" | 10:| style="border-left: none;" | ad| style="border-right: none;" | 11:| style="border-left: none;" | d?
|-
| 01111 1001 || 159| style="text-align: center;" | Oaba| style="border-right: none;" | 2711:| style="border-left: none;" | TOda| style="border-right: none;" | 2812:| style="border-left: none;" | Oaba? |-| 1000 || 8| style="text-align: center;" | ca| style="border-right: none;" | 12:| style="border-left: none;" | abac| style="border-right: none;" | 13:| style="border-left: none;" | ca?|-|0110 || 6| style="text-align: center;" | ba| style="border-right: none;" | 13:| style="border-left: none;" | cab| style="border-right: none;" | 14:| style="border-left: none;" | ba?|-| 0100 || 4| style="text-align: center;" | e| style="border-right: none;" | 14:| style="border-left: none;" | bae| style="border-right: none;" | -| style="border-left: none;" | -|-|} === Примечание === Для повышения степени сжатия изображений данным методом часто используется одна “хитрость” реализации этого алгоритма. Некоторые файлы, подвергаемые сжатию с помощью LZW, имеют часто встречающиеся цепочки одинаковых символов, например <tex>aaaaaaaaaaaaa... </tex> или <tex>303030</tex> … и т. п. Их непосредственное сжатие будет генерировать выходной код <tex>005000600007...</tex>. Спрашивается, можно ли в этом частном случае повысить степень сжатия? Оказывается, это возможно, если оговорить некоторые действия: Мы знаем, что для каждого кода надо добавлять в таблицу строку, состоящую из уже присутствующей там строки и символа, с которого начинается следующая строка в потоке.*''' ''' Пусть словарь состоит из слов : <tex>a, b, c, d, e</tex>. Будем кодировать строку <tex> aaaaaaaaaa </tex>*''' ''' Итак, кодировщик заносит первую <tex>a</tex> в строку, ищет и находит <tex>a</tex> в словаре под номером <tex>\langle0\rangle</tex>. Добавляет в строку следующую <tex>a</tex>, находит, что <tex>aa</tex> нет в словаре. Тогда он добавляет запись <tex>\langle5\rangle</tex>: <tex>aa</tex> в словарь и выводит метку <tex>\langle0\rangle</tex> (<tex>a</tex>) в выходной поток. *''' '''Далее строка инициализируется второй <tex>a</tex>, то есть принимает вид <tex>a?</tex> вводится третья <tex>a</tex>, строка вновь равна <tex>aa</tex>, которая теперь имеется в словаре. *''' '''Если появляется четвертая <tex>a</tex>, то строка <tex>aa?</tex> равна <tex>aaa</tex>, которой нет в словаре. Словарь пополняется этой строкой, а на выход идет метка <tex>\langle5\rangle</tex> (<tex>aa</tex>). *''' '''После этого строка инициализируется третьей <tex>a</tex>, и т.д. и т.п. Дальнейший процесс вполне ясен.  [[Файл:LZW-img.jpg|center|Работа алгоритма LZW]] {| class="wikitable" border = 1, style="text-align: center; margin-left: auto; margin-right: auto;"|- bgcolor=#EEEEEE! Слово !! Номер в словаре
|-
| 00010 || 2| style="text-align: center;" | B| style="border-right: none;" | 28:| style="border-left: none;" | OB| style="border-right: none;" | 29:| style="border-left: none;" | B? a ||<tex>\langle0\rangle</tex>
|-
| 00101 || 5| style="text-align: center;" | E| style="border-right: none;" | 29:| style="border-left: none;" | BE| style="border-right: none;" | 30:| style="border-left: none;" | E? b ||<tex>\langle1\rangle</tex>
|-
| 01111 || 15| style="text-align: center;" | O| style="border-right: none;" | 30:| style="border-left: none;" | EO| style="border-right: none;" | 31:| style="border-left: none;" | O? c ||<tex>\langle2\rangle</tex>
|-
| 10010 d || 18| style="text-align: center;" | R| style="border-right: none;" | 31:| style="border-left: none;" | OR| style="border-right: none;" | 32:| style="border-left: none;" | R?| style="text-align: left;" | создали код 31 (последний, содержащий 5 бит)<tex>\langle3\rangle</tex>
|-
| 001110 e || 14<tex>\langle4\rangle</tex>| } {| class="wikitable" border =1, style="text-align: center; margin-left: auto; margin-right: auto;" | N- bgcolor =#EEEEEE| style! scope="col" width="6em" rowspan="border-right: none;2" | 32:Текущая строка| style! scope="col" width="6em" rowspan="border-left: none;2" | RNТекущий символ| style! scope="col" width="4em" rowspan="border-right: none;2" | 33:Следующий символ| style! colspan="border-left: none;2" | N?Вывод| style! scope="col" width="7em" rowspan="2" colspan="text-align: left;2" | начинаем Словарь|- bgcolor =#EEEEEE! использовать 6 битКод || Биты
|-
| 001111 || 15| style="text-align: center;" | Oaa| style="bordertext-rightalign: nonecenter;" | 33:a| style="bordertext-leftalign: nonecenter;" | NOa| 0 || 000| style="border-right: none;" | 345:| style="border-left: none;" | O? ||aa
|-
| 010100 || 20| style="text-align: center;" | Taa| style="bordertext-rightalign: nonecenter;" | 34:a| style="bordertext-leftalign: nonecenter;" | OTa| - || -| style="border-right: none;" | 35:-| style="border-left: none;" | T? ||-
|-
| 011011 || 27| style="text-align: center;" | TOaaa| style="bordertext-rightalign: nonecenter;" | 35:a| style="bordertext-leftalign: nonecenter;" | TTa| 5 || 101| style="border-right: none;" | 366:| style="border-left: none;" | TO? ||aaa
|-
| 011101 || 29| style="text-align: center;" | BEa| style="bordertext-rightalign: nonecenter;" | 36:a| style="bordertext-leftalign: nonecenter;" | TOBa| - || -| style="border-right: none;" | 37:-| style="border-left: none;" | BE?| style="text-align: left;" | 36 = TO + 1й символ (B)
|-
| 011111 || 31| style="text-align: center;" | ORaa| style="bordertext-rightalign: nonecenter;" | 37:a| style="bordertext-leftalign: nonecenter;" | BEOa| - || -| style="border-right: none;" | 38:-| style="border-left: none;" | OR?| style="text-align: left;" | следующей полученной последовательности (BE)
|-
| 100100 || 36| style="text-align: center;" | TOBaaa| style="bordertext-rightalign: nonecenter;" | 38:a| style="bordertext-leftalign: nonecenter;" | ORTa| - || -| style="border-right: none;" | 39:-| style="border-left: none;" | TOB? ||-
|-
| 011110 || 30| style="text-align: center;" | EOaaaa| style="bordertext-rightalign: nonecenter;" | 39:a| style="bordertext-leftalign: nonecenter;" | TOBEa| 6 || 110| style="border-right: none;" | 407:| style="border-left: none;" | EO? ||aaaa
|-
| 100000 || 32| style="text-align: center;" | RNa| style="bordertext-rightalign: nonecenter;" | 40:a| style="bordertext-leftalign: nonecenter;" | EORa| - || -| style="border-right: none;" | 41:-| style="border-left: none;" | RN? ||-
|-
| 100010 || 34| style="text-align: center;" | OTaa| style="bordertext-rightalign: nonecenter;" | 41:a| style="bordertext-leftalign: nonecenter;" | RNOa| - || -| style="border-right: none;" | 42:-| style="border-left: none;" | OT? ||- 
|-
| 000000 || 0| style="text-align: center;" | #aaa| style="bordertext-rightalign: nonecenter;" | a| style="bordertext-leftalign: nonecenter;" |a| - || -| style="border-right: none;" |-| style="border-left: none;" | ||-
|-
| style="text-align: center;" | aaaa
| style="text-align: center;" | a
| style="text-align: center;" | a
| 7 || 111
| style="border-right: none;" | 8:
| style="border-left: none;" | aaaaa
|}
Единственная небольшая трудность может возникнутьВ результате на выходе получаем последовательность <tex>0567</tex>. При кодировании использовались только трехбитные группы. Длина закодированного сообщения составила <tex> 4 \cdot 3 = 12 </tex> бит, если новое слово словаря пересылается немедленночто на <tex> 7 \cdot 3 - 12 = 9</tex> бит короче кодирования стандартным методом LZW. В приведённом выше примере декодированияМожно показать, когда декодер встречает что такая последовательность будет корректно восстановлена. Декодировщик сначала читает первый код – это <tex>\langle0\rangle</tex>, которому соответствует символ<tex>a</tex>. Затем читает код <tex>\langle5\rangle</tex>, '''T'''но этого кода в его таблице нет. Но мы уже знаем, он знаетчто такая ситуация возможна только в том случае, когда добавляемый символ равен первому символу только что слово 27 начинается считанной последовательности, то есть <tex>a</tex>. Поэтому он добавит в свою таблицу строку <tex>aa</tex> с Tкодом <tex>\langle5\rangle</tex>, а в выходной поток поместит <tex>aa</tex>. И так может быть раскодирована вся цепочка кодов. Мало того, описанное выше правило кодирования мы можем применять в общем случае не только к подряд идущим одинаковым символам, но чем оно заканчивается? Проиллюстрируем проблему следующим примероми к последовательностям, у которых очередной добавляемый символ равен первому символу цепочки. Мы декодируем сообщение '''ABABA''': Данные: На выходе: Новая запись: Полная: Частичная:=== Преимущества алгоритма LZW ===  * Алгоритм является однопроходным. * Для декомпрессии не надо сохранять таблицу строк в файл для распаковки. Алгоритм построен таким образом, что мы в состоянии восстановить таблицу строк, пользуясь только потоком кодов. === Недостатки алгоритма LZW === * Алгоритм не проводит анализ входных данных. 011101 ==Источники информации== 29 AB 46 * [http: (word) 47//ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B5%D0%BC%D0%BF%D0%B5%D0%BB%D1%8F_%E2%80%94_%D0%97%D0%B8%D0%B2%D0%B0_%E2%80%94_%D0%92%D0%B5%D0%BB%D1%87%D0%B0 Википедия {{---}} Алгоритм Лемпеля {{---}} Зива {{---}} Велча] * [http: AB?//en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Welch 101111 = 47 AB? <Wikipedia {{---}} Lempel {{---}} Ziv {{--- что нам с этим делать?}} Welch]
На первый взгляд, для декодера это неразрешимая ситуация* [http://compression. Мы знаем наперёд, что словом 47 должно быть '''ABA''', но как декодер узнает об этом?Заметим, что слово 47 состоит из слова 29 плюс символ идущий следующимru/download/articles/rev_univ/semenyuk_2001_econom_encoding. Таким образом, слово 47 заканчивается на «символ идущий следующим»pdf Семенюк В. Но, поскольку это слово посылается немедленно, то оно должно начинаться с «символа идущего следующим», и поэтому оно заканчивается тем же символом что и начинается, в данном случае — '''A'''. Этот трюк позволяет декодеру определить, что слово 47 это '''ABA'''В.{{---}} Экономное кодирование дискретной информации]
В общем случае, такая ситуация появляется, когда кодируется последовательность вида ''cScSc'', где ''c'' — это один символ, а ''S'' — строка, причём слово ''cS'' уже есть в словаре* [http://algolist.manual.ru/compress/standard/lzw.php Метод LZW {{---}} сжатия данных {{---}} алгоритмы и методы]
== Патенты ==На алгоритм LZW и его вариации был выдан ряд патентов, как в США, так и в других странах* [http://www.compression-pointers. К настоящему времени, сроки всех патентов истеклиru/category_42.html Алгоритмы сжатия и компрессии]
=== Unisys, GIF и PNG ===При разработке формата GIF в CompuServe не знали о существовании патента. В декабре 1994 года, когда в Unisys стало известно об использовании LZW в широко используемом графическом формате, эта компания распространила информацию о своих планах по взысканию лицензионных отчислений с коммерческих программ, имеющих возможность по созданию GIF-файлов* [http://www. В то время формат был уже настолько широко распространён, что большинство компаний-производителей ПО не имели другого выхода кроме как заплатитьalgoritmy. Эта ситуация стала одной из причин разработки графического формата PNG (неофициальная расшифровка: «PNG’s Not GIF»), ставшего третьим по распространённости в Интеренете, после GIF и JPEGinfo/picture5. В конце августа 1999 года Unisys прервала действие безвозмездных лицензий на LZW для бесплатного и некоммерческого ПО, а также для пользователей нелицензированных программ, призвав ''League for Programming Freedom'' развернуть кампанию «сожжём все GIF’ы» и информировать публику об имеющихся альтернативах. Многие эксперты в области патентного права отмечали, что патент не распространяется на устройства, которые могут лишь разжимать html Алгоритм LZW{{--данные, но не сжимать их; по этой причине, популярная утилита gzip может читать .Z-файлы, но не записывать их.}} Понятие алгоритма]
20 июня 2003 года истёк срок оригинального американского патента, что означает, что Unisys не может больше собирать по нему лицензионные отчисления. Аналогичные патенты в Европе, Японии [[Категория: Дискретная математика и Канаде истекли в 2004 году.алгоритмы]][[Категория: Алгоритмы сжатия]]
1632
правки

Навигация