Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Сжатие информации.doc
Скачиваний:
5
Добавлен:
24.04.2019
Размер:
315.9 Кб
Скачать
  1. Сжатие информации с учетом цепочек символов по Лемпелю-Зиву (Велчу).

Очевидно, что посимвольное кодирование не использует резервы сжатия информации, связанные с повторяемостью цепочек символов. Так например, в исходном тексте программы на алгоритмическом языке часто встречаются повторяющиеся наименования операторов или идентификаторы, которые в принципе можно закодировать короткими битовыми последовательностями.

Наиболее удачным алгоритмом сжатия, основанным на таком подходе является алгоритм Лемпеля-Зива, который в разных модификациях используется, в частности, в большинстве программ-архиваторов. Основная идея алгоритма состоит в том, что цепочки символов, уже встреченные ранее кодируются ссылкой на их «координаты» (номер первого символа и длину) в «словаре», где находится уже обработанная часть сообщения.

Суть его в следующем: упаковщик постоянно хранит некоторое количество последних обработанных символов в буфере. По мере обработки входного потока вновь поступившие символы попадают в конец буфера, сдвигая предшествующие символы и вытесняя самые старые. Размеры этого буфера, называемого также скользящим словарем (sliding dictionary), варьируются в разных реализациях (в LHarc 1.13 используется 4-килобайтный буфер, LHA 2.13 и PKZIP 1.10 - 8-килобайтный, а ARJ 2.20 - 16-килобайтный).

Алгоритм выделяет (путем поиска в словаре) самую длинную начальную подстроку входного потока, совпадающую с одной из подстрок в словаре, и выдает на выход пару (length, distance), где length - длина найденной в словаре подстроки, а distance - расстояние от нее до входной подстроки (то есть фактически индекс подстроки в буфере, вычтенный из его размера). В случае, если такая подстрока не найдена, в выходной поток просто копируется очередной символ входного потока.

В первоначальной версии алгоритма предлагалось использовать простейший поиск по всему словарю. Время сжатия при такой реализации было пропорционально произведению длины входного потока на размер буфера, что непригодно для практического использования. Однако, в дальнейшем было предложено использовать двоичное дерево для быстрого поиска в словаре, что позволило на порядок поднять скорость работы алгоритма.

Таким образом, алгоритм Лемпеля-Зива преобразует один поток исходных символов в два параллельных потока length и distance. Очевидно, что эти потоки являются потоками символов в новых алфавитах L и D, и к ним можно применить один из упоминавшихся выше методов (RLE, кодирование Хаффмана, арифметическое кодирование). Так мы приходим к схеме двухступенчатого кодирования, наиболее эффективной из практически используемых в настоящее время (и, в частности, использованной автором). При реализации этого метода необходимо добиться согласованного вывода обоих потоков в один файл. Эта проблема обычно решается путем поочередной записи кодов символов из обоих потоков.

Уточним дополнительно некоторые моменты:

- коды координат цепочки и коды отдельных символов различаются битовыми признаками (например, в первом случае – 1, во втором –0) ;

  • поскольку цепочки находятся чаще в начале словаря, и чаще бывают короткими, дополнительный выигрыш получают за счет статистического кодирования (по Хаффмену) их «адресов» и «длин»;

  • «канал» - понятие применимое и к реальному каналу передачи данных, и к файлу, куда данные записываются для хранения. В последнем случае декодер «отрабатывает» при разворачивании сжатого файла;

  • при ограниченной длине словаря (обычно от 4 до 16 кбайт) новые поступающие символы и цепочки «вытесняют» прежние (текст как бы «вдвигается» в словарь). Разумеется, вначале, когда словарь не заполнен, эффективность сжатия невысока. Рост объема словаря позволяет повысить степень сжатия, но значительно увеличивается трудоемкость поиска цепочек.

Добавим, что алгоритм Лемпеля-Зива используется в большинстве популярных программ-архиваторов (в том числе, например, в zip, rar, arj и их windows – версиях). Различие скорости и эффективности кодирование-декодирование определяются в основном особенностями программной реализации.

Алгоритм Лемпеля-Зива требует большого количества вычислительной работы. Его модификация - алгоритм Лемпеля-Зива-Велча является менее трудоемким, хотя и дает несколько худшие результаты по сжатию.

Алгоритм упаковки Лемпеля-Зива-Велча (Lempel-Ziv-Welch compression, LZW) работает так. Будем предполагать, что входной алфавит состоит из m различных символов.

1. Инициализация словаря. В пустой словарь помещаются все m различных односимвольных строк.

2. Строке P, называемой "префиксом", присваиваем пустое значение.

3. Пусть k - очередной символ входного потока.

4. Ищем строку P+k в словаре.

Если нашли, то P := P+k,

сдвигаем указатель входного потока на следующий символ,

переходим к п. 3.

иначе

выводим номер строки P в словаре в выходной поток,

добавляем строку P+k в словарь,

P := k (строка длины 1),

сдвигаем указатель входного потока на

length(P) символов,

переходим к п.3

конец_если.