Особенности алгоритма LZSS, что такое Unicode

Новый международный стандартный коде Unicode был разработан и предложен для употребления международной организацией Unicode (Unicode.org). В этом коде используются 16-битные последовательности для кодирования символов, что дает 2^16 = 64К = 65536 различных символов. Unicode содержит все ASCII коды плюс коды для букв иностранных языков (включая такие сложные алфавиты, как корейский, китайский и японский), а кроме того многие математические символы и другие знаки. К настоящему времени около 39000 из 65536 кодов получили назначение, но еще остается много места для добавления новых символов в будущем. Операционная система Microsoft Windows NT поддерживает коды Unicode.
Единственное место, где успех приходит до работы - это в словаре. Видал Сассон.

Пример: Покажем, как двоичное дерево способно ускорить поиск в словаре. Пусть входной файл содержит следующую последовательность: «sid_eastman_cl\imsily_teases_sea_sick_seals». Для простоты предположим, что окно состоит из 1б-байтного буфера поиска и 5-байтного упреждающего буфера. После ввода первых 16+5 символов скользящее окно выглядит так: sid_eastman_clum sily_ teases_sea_sick_seals причем подпоследовательность teases_sea_sick_seals ждет своей очереди на входе. Кодер изучает буфер поиска, создавая двенадцать строк по пять символов (их двенадцать, так как 12 = 16 — 5 + 1), которые помещены на двоичное дерево поиска вместе с их смещениями.

Первым символом в упреждающем буфере является s, поэтому кодер ищет на дереве строки, начинающиеся на s. Он находит две строки со смещениями 16 и 10, но первая из них, sid_e, имеет более длинное совпадение. (Здесь необходимо отвлечься и обсудить случай, когда строка на дереве полностью совпадает с содержимым упреждающего буфера. Тогда кодер мог бы искать дальнейшие совпадения. В принципе, длина совпадения может быть L — 1.) В нашем примере длина совпадения равна 2, поэтому кодер выдает метку (16,2). Теперь кодер должен переместить скользящее окно на две позиции вправо и перестроить дерево.

С дерева необходимо удалить строки sid_e и id_ea и вставить новые строки clums и liimsi. Если бы случилось совпадение длины n, то дерево надо было бы перестроить путем удаления к строк и добавления к строк, но вот каких? Немного подумав, становится ясно, что удаляться будут первые к строк буфера поиска до его сдвига, а добавляться будут последние к строк этого буфера после сдвига. Простейшая процедура обновления дерева состоит в приготовлении строк из начала буфера, их поиска и удаления. Потом необходимо сдвинуть буфер на одну позицию вправо (или переместить данные на одну позицию влево), приготовить строку из последних 5 символов буфера поиска и добавить ее на дерево. Это следует повторить к раз. (Конец примера.)

На дереве все время находится одинаковое число Т узлов или строк, поскольку при его обновлении удаляется и добавляется одно и то же число строк. Число Т равно: длина буфера поиска минус длина упреждающего буфера плюс 1 (Т = S — L-1-1). Однако, форма дерева может существенно измениться. Поскольку узлы удаляются и добавляются, то форма дерева может меняться от абсолютно косой (худший случай для поиска) до сбалансированной, идеальной формы. Третье улучшение метода LZ77 в алгоритме LZSS касалось создаваемых кодером меток. Метка LZSS состоит только из смещения и длины. Если не найдено совпадений, то кодер просто подает на выход несжатый код следующего символа вместо расточительной метки из трех полей (0,0,...).

Для различения меток и несжатых кодов используется флаговый бит. На практике буфер поиска может состоять из нескольких сотен байт, поэтому поле смещения, обычно, состоит из 11-13 бит. Размер упреждающего буфера выбирается с таким условием, чтобы в сумме с буфером поиска длина составляла 16 бит (2 байта). Например, если буфер поиска имеет размер 2 KB (= 2^11), то упреждающий буфер состоит из 32 байт (= 2^5). Длина поля смещения равна 11, а поле «длина» имеет 5 разрядов. При таком выборе размеров буферов кодер будет выдавать или 2-х байтовую метку или 1-байтовый несжатый код ASCII. А как насчет флага? Хороший практический совет состоит в накоплении восьми последоватезльных выходов (меток или ASCII кодов) в маленьком буфере, затем выдавать один байт из 8 флагов, за которым следуют восемь накопленных элементов по 2 или 1 байту.

-----------------------------