<?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=178.94.18.98&amp;*</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=178.94.18.98&amp;*"/>
		<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/178.94.18.98"/>
		<updated>2026-04-12T20:13:20Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_LZ77_%D0%B8_LZ78&amp;diff=73943</id>
		<title>Алгоритмы LZ77 и LZ78</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_LZ77_%D0%B8_LZ78&amp;diff=73943"/>
				<updated>2020-04-21T10:04:16Z</updated>
		
		<summary type="html">&lt;p&gt;178.94.18.98: offset &amp;gt; length !!!!&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex&amp;gt;\mathrm{LZ77}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm{LZ78}&amp;lt;/tex&amp;gt; {{---}} алгоритмы сжатия без потерь, опубликованные Абрахамом Лемпелем&amp;lt;ref&amp;gt;[https://en.wikipedia.org/wiki/Abraham_Lempel Wikipedia {{---}} Abraham Lempel]&amp;lt;/ref&amp;gt; и Якобом Зивом&amp;lt;ref&amp;gt;[https://en.wikipedia.org/wiki/Yaakov_Ziv Wikipedia {{---}} Yaakov Ziv]&amp;lt;/ref&amp;gt; в &amp;lt;tex&amp;gt;1977&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;1978&amp;lt;/tex&amp;gt; годах соответственно. Эти алгоритмы стали основой других алгоритмов семьи &amp;lt;tex&amp;gt;\mathrm{LZ*}&amp;lt;/tex&amp;gt;: [[Алгоритм_LZW|LZW]], [[Алгоритм_LZSS|LZSS]], [[Алгоритм_LZMA|LZMA]] и другие. Оба приведенных алгоритма используют словарный подход.&lt;br /&gt;
&lt;br /&gt;
== LZ77 ==&lt;br /&gt;
&lt;br /&gt;
=== Идея алгоритма === &lt;br /&gt;
В кодируемых строках часто содержатся совпадающие длинные подстроки. Идея, лежащая в основе &amp;lt;tex&amp;gt;\mathrm{LZ77}&amp;lt;/tex&amp;gt;, заключается в замене повторений на ссылки на позиции в тексте, где такие подстроки уже встречались.&lt;br /&gt;
&lt;br /&gt;
Информацию о повторении можно закодировать парой чисел {{---}} смещением назад от текущей позиции (&amp;lt;tex&amp;gt;offset&amp;lt;/tex&amp;gt;) и длиной совпадающей подстроки (&amp;lt;tex&amp;gt;length&amp;lt;/tex&amp;gt;). В таком случае, например, строка &amp;lt;tex&amp;gt;pabcdeqabcde&amp;lt;/tex&amp;gt; может быть представлена как &amp;lt;tex&amp;gt;pabcdeq \langle 6, 5 \rangle&amp;lt;/tex&amp;gt;. Выражение &amp;lt;tex&amp;gt;\langle 6, 5 \rangle&amp;lt;/tex&amp;gt; означает «вернись на &amp;lt;tex&amp;gt;6&amp;lt;/tex&amp;gt; символов назад и выведи &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; символов».&lt;br /&gt;
&lt;br /&gt;
Алгоритм &amp;lt;tex&amp;gt;\mathrm{LZ77}&amp;lt;/tex&amp;gt; кодирует ссылки блоками из трёх элементов {{---}} &amp;lt;tex&amp;gt;\langle offset, length, next \rangle&amp;lt;/tex&amp;gt;. В дополнение к двум уже описанным элементам, новый параметр &amp;lt;tex&amp;gt;next&amp;lt;/tex&amp;gt; означает первый символ после найденного совпадающего фрагмента. Если &amp;lt;tex&amp;gt;\mathrm{LZ77}&amp;lt;/tex&amp;gt; не удалось найти совпадение, то считается, что &amp;lt;tex&amp;gt;offset = length = 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LZ77-simple-example.jpg]]&lt;br /&gt;
&lt;br /&gt;
Для эффективного поиска повторов в &amp;lt;tex&amp;gt;\mathrm{LZ77}&amp;lt;/tex&amp;gt; применяется метод «скользящего окна» {{---}} совпадения ищутся не на всём обработанном префиксе, а в небольшом буфере, состоящем из последних обработанных символов. Обычно длина буфера равна &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;32 \mathrm{KB}&amp;lt;/tex&amp;gt;. Таким образом, при больших объемах ввода алгоритм тратит меньше времени за счет того, что просматривается не вся исходная строка. С другой стороны, слишком маленькая длина словаря может привести к тому, что расположенные далеко друг от друга совпадения (на большем расстоянии, чем длина словаря) не будут учтены, и кодирование станет менее оптимальным.&lt;br /&gt;
&lt;br /&gt;
Также нетривиальным может оказаться то, что при кодировании &amp;lt;tex&amp;gt;\mathrm{LZ77}&amp;lt;/tex&amp;gt; значение &amp;lt;tex&amp;gt;offset&amp;lt;/tex&amp;gt; может быть меньше, чем &amp;lt;tex&amp;gt;length&amp;lt;/tex&amp;gt; (например, «вернись на &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; символа назад и выведи &amp;lt;tex&amp;gt;10&amp;lt;/tex&amp;gt; символов»). Это означает, что подстрока будет повторяться несколько раз так, чтобы каждый символ совпадал с символом, стоящим на &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; позиции раньше, и всего добавилось &amp;lt;tex&amp;gt;10&amp;lt;/tex&amp;gt; символов. Например: &amp;lt;tex&amp;gt;hello\langle 2, 10 \rangle \Leftrightarrow hello\boldsymbol{lololololo}&amp;lt;/tex&amp;gt;. Символ всегда можно определить однозначно, даже если он отсутствует в буфере.&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
&lt;br /&gt;
Хранить результат кодирования будем в списке структур следующего вида:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''struct''' Node:&lt;br /&gt;
     '''int''' offset&lt;br /&gt;
     '''int''' length&lt;br /&gt;
     '''char''' next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция &amp;lt;code&amp;gt;findMatching&amp;lt;/code&amp;gt; ищет в буфере строку, совпадающую с префиксом суффикса строки &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;, начинающегося с символа &amp;lt;tex&amp;gt;pos&amp;lt;/tex&amp;gt; и возвращает искомую пару &amp;lt;tex&amp;gt;\langle offset, length \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Функция &amp;lt;code&amp;gt;shiftBuffer&amp;lt;/code&amp;gt; сдвигает буфер вперёд на &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; символов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} исходная строка&lt;br /&gt;
 // функция возвращает список блоков &amp;lt;tex&amp;gt;\langle offset, length, next \rangle&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''list&amp;lt;Node&amp;gt;''' encodeLZ77('''string''' s):&lt;br /&gt;
    '''list&amp;lt;Node&amp;gt;''' ans = []&lt;br /&gt;
    pos = 0&lt;br /&gt;
    '''while''' pos &amp;lt; s.length:&lt;br /&gt;
        offset, length = findMatching(buffer, pos)   &amp;lt;font color=green&amp;gt;// ищем слово в словаре&amp;lt;/font&amp;gt;&lt;br /&gt;
        shiftBuffer(length + 1)                      &amp;lt;font color=green&amp;gt;// перемещаем скользящее окно&amp;lt;/font&amp;gt;&lt;br /&gt;
        pos += length&lt;br /&gt;
        ans.push({offset, length, s[pos]})           &amp;lt;font color=green&amp;gt;// добавляем в ответ очередной блок&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''return''' ans&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;\mathrm{LZ77}&amp;lt;/tex&amp;gt; на строке &amp;lt;tex&amp;gt;abacabacabadaca&amp;lt;/tex&amp;gt; с буфером размера &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt;. Квадратом обведен буфер.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Строка || Совпадение || Закодированная последовательность || Примечание&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;abacabacabadaca&amp;lt;/tex&amp;gt; || {{---}} || &amp;lt;tex&amp;gt;\langle 0, 0, a \rangle&amp;lt;/tex&amp;gt; || Буфер пуст&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;\fbox{$a$}bacabacabadaca&amp;lt;/tex&amp;gt; || {{---}} || &amp;lt;tex&amp;gt;\langle 0, 0, b \rangle&amp;lt;/tex&amp;gt; || В буфере нет &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;\fbox{$ab$}acabacabadaca&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\langle 2, 1, c \rangle&amp;lt;/tex&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;\fbox{$abac$}abacabadaca&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;abacaba&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\langle 4, 7, d \rangle&amp;lt;/tex&amp;gt; || Здесь выгодно сделать так, что &amp;lt;tex&amp;gt;offset &amp;lt; length&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;abacaba\fbox{$cabad$}aca&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\langle 2, 1, c \rangle&amp;lt;/tex&amp;gt; || Последовательность &amp;lt;tex&amp;gt;aca&amp;lt;/tex&amp;gt; уже встречалась, но она находится за пределами окна, и &amp;lt;tex&amp;gt;\mathrm{LZ77}&amp;lt;/tex&amp;gt; её не находит&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;abacabaca\fbox{$badac$}a&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\langle 2, 1, \varnothing \rangle&amp;lt;/tex&amp;gt; || Символов в строке больше нет, поэтому в качестве &amp;lt;tex&amp;gt;next&amp;lt;/tex&amp;gt; ставим символ конца строки&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Результатом кодирования является список полученных троек: &amp;lt;tex&amp;gt;\left[ \langle 0, 0, a \rangle, \langle 0, 0, b \rangle, \langle 2, 1, c \rangle, \langle 4, 7, d \rangle, \langle 2, 1, c \rangle, \langle 2, 1, \varnothing \rangle \right]&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Декодирование ===&lt;br /&gt;
Для декодирования &amp;lt;tex&amp;gt;\mathrm{LZ77}&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;
 &amp;lt;font color=green&amp;gt;// &amp;lt;tex&amp;gt;encoded&amp;lt;/tex&amp;gt; {{---}} список блоков &amp;lt;tex&amp;gt;\langle offset, length, next \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
 // функция возвращает декодированную строку&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''string''' decodeLZ77('''list&amp;lt;Node&amp;gt;''' encoded):&lt;br /&gt;
     ans = &amp;quot;&amp;quot;&lt;br /&gt;
     '''for''' node '''in''' encoded:&lt;br /&gt;
         '''if''' node.length &amp;gt; 0:                         &amp;lt;font color=green&amp;gt;// если необходим повтор&amp;lt;/font&amp;gt;&lt;br /&gt;
             start = ans.length - node.offset        &amp;lt;font color=green&amp;gt;// возвращаемся на &amp;lt;tex&amp;gt;offset&amp;lt;/tex&amp;gt; символов назад&amp;lt;/font&amp;gt;&lt;br /&gt;
             '''for''' i = 0 .. node.length - 1:           &amp;lt;font color=green&amp;gt;// добавляем &amp;lt;tex&amp;gt;length&amp;lt;/tex&amp;gt; символов&amp;lt;/font&amp;gt;&lt;br /&gt;
                 ans += ans[start + i]&lt;br /&gt;
         ans += node.next                            &amp;lt;font color=green&amp;gt;// добавляем следующий символ&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''return''' ans&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Модификации ===&lt;br /&gt;
Известно много различных модификаций алгоритма &amp;lt;tex&amp;gt;\mathrm{LZ77}&amp;lt;/tex&amp;gt;. Например, вместо блоков можно хранить отдельно одиночные символы и отдельно {{---}} пары &amp;lt;tex&amp;gt;\langle offset, length \rangle&amp;lt;/tex&amp;gt; (length-distance pair&amp;lt;ref&amp;gt;[https://en.wikipedia.org/wiki/LZ77_and_LZ78#LZ77 Wikipedia {{---}} LZ77]&amp;lt;/ref&amp;gt;). [[Алгоритм LZSS]] является улучшением &amp;lt;tex&amp;gt;\mathrm{LZ77}&amp;lt;/tex&amp;gt; и хранит однобитный флаг, показывающий, какие данные за ним идут: одиночный символ или пара смещения и длины. В формате &amp;lt;tex&amp;gt;\mathrm{PalmDoc}&amp;lt;/tex&amp;gt;&amp;lt;ref&amp;gt;[https://wiki.mobileread.com/wiki/PalmDOC Описание формата PalmDOC]&amp;lt;/ref&amp;gt; на каждую пару смещения и длины выделяется по &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; байта.&lt;br /&gt;
&lt;br /&gt;
Также на &amp;lt;tex&amp;gt;\mathrm{LZ77}&amp;lt;/tex&amp;gt; основаны алгоритмы &amp;lt;tex&amp;gt;\mathrm{LZH}&amp;lt;/tex&amp;gt;&amp;lt;ref&amp;gt;[https://msdn.microsoft.com/en-us/library/hh554076.aspx LZH]&amp;lt;/ref&amp;gt; и &amp;lt;tex&amp;gt;\mathrm{DEFLATE}&amp;lt;/tex&amp;gt;&amp;lt;ref&amp;gt;[https://en.wikipedia.org/wiki/DEFLATE Wikipedia {{---}} DEFLATE]&amp;lt;/ref&amp;gt; (последний является широко используемым), которые совмещают &amp;lt;tex&amp;gt;\mathrm{LZ77}&amp;lt;/tex&amp;gt; с [[Алгоритм Хаффмана|алгоритмом Хаффмана]], кодируя элементы пар и одиночные символы.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LZ78 ==&lt;br /&gt;
&lt;br /&gt;
=== Идея алгоритма ===&lt;br /&gt;
Алгоритм &amp;lt;tex&amp;gt;\mathrm{LZ78}&amp;lt;/tex&amp;gt; имеет немного другую идею: этот алгоритм в явном виде использует словарный подход, генерируя временный словарь во время кодирования и декодирования.&lt;br /&gt;
&lt;br /&gt;
Изначально словарь пуст, а алгоритм пытается закодировать первый символ. На каждой итерации мы пытаемся увеличить кодируемый префикс, пока такой префикс есть в словаре. Кодовые слова такого алгоритма будут состоять из двух частей {{---}} номера в словаре самого длинного найденного префикса (&amp;lt;tex&amp;gt;pos&amp;lt;/tex&amp;gt;) и символа, который идет за этим префиксом (&amp;lt;tex&amp;gt;next&amp;lt;/tex&amp;gt;). При этом после кодирования такой пары префикс с приписанным символом добавляется в словарь, а алгоритм продолжает кодирование со следующего символа.&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
&lt;br /&gt;
Будем хранить результат кодирования в такой структуре:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''struct''' Node:&lt;br /&gt;
     '''int''' pos   &amp;lt;font color=green&amp;gt;// номер слова в словаре&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''char''' next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В качестве словаря будем использовать обычный &amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''list&amp;lt;Node&amp;gt;''' encodeLZ78('''string''' s):&lt;br /&gt;
     '''string''' buffer = &amp;quot;&amp;quot;                              &amp;lt;font color=green&amp;gt;// текущий префикс&amp;lt;/font&amp;gt;             &lt;br /&gt;
     '''map&amp;lt;string, int&amp;gt;''' dict = {}                      &amp;lt;font color=green&amp;gt;// словарь&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''list&amp;lt;Node&amp;gt;''' ans = []                             &amp;lt;font color=green&amp;gt;// ответ&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''for''' i = 0 .. s.length - 1:&lt;br /&gt;
         '''if''' dict.hasKey(buffer + s[i]):              &amp;lt;font color=green&amp;gt;// можем ли мы увеличить префикс&amp;lt;/font&amp;gt;&lt;br /&gt;
             buffer += s[i]&lt;br /&gt;
         '''else''':&lt;br /&gt;
             ans.push({dict[buffer], s[i]})          &amp;lt;font color=green&amp;gt;// добавляем пару в ответ&amp;lt;/font&amp;gt;&lt;br /&gt;
             dict[buffer + s[i]] = dict.length + 1   &amp;lt;font color=green&amp;gt;// добавляем слово в словарь&amp;lt;/font&amp;gt;&lt;br /&gt;
             buffer = &amp;quot;&amp;quot;                             &amp;lt;font color=green&amp;gt;// сбрасываем буфер&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''if''' not (buffer is empty): &amp;lt;font color=green&amp;gt;// если буффер не пуст - этот код уже был, нужно его добавить в конец словаря&amp;lt;/font&amp;gt;&lt;br /&gt;
         last_ch = buffer.peek() &amp;lt;font color=green&amp;gt;// берем последний символ буффера, как &amp;quot;новый&amp;quot; символ&amp;lt;/font&amp;gt;&lt;br /&gt;
         buffer.pop() &amp;lt;font color=green&amp;gt;// удаляем последний символ из буфера&amp;lt;/font&amp;gt;&lt;br /&gt;
         ans.push({dict[buffer], last_ch}) &amp;lt;font color=green&amp;gt;// добавляем пару в ответ&amp;lt;/font&amp;gt; &lt;br /&gt;
     '''return''' ans&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;abacababacabc&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Словарь || Осталось обработать || Найденный префикс || Код || Примечание&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;abacababacabc&amp;lt;/tex&amp;gt; || {{---}} || &amp;lt;tex&amp;gt;\langle 0, a \rangle&amp;lt;/tex&amp;gt; || В словаре ничего не нашлось, вместо номера в словаре указываем &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;bacababacabc&amp;lt;/tex&amp;gt; || {{---}} || &amp;lt;tex&amp;gt;\langle 0, b \rangle&amp;lt;/tex&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;acababacabc&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\langle 1, c \rangle&amp;lt;/tex&amp;gt; || Нашелся префикс &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (слова в словаре нумеруются с &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;), добавляем &amp;lt;tex&amp;gt;ac&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;ac&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;ababacabc&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\langle 1, b \rangle&amp;lt;/tex&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;ac&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;ab&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;abacabc&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;ab&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\langle 4, a \rangle&amp;lt;/tex&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;ac&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;ab&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;aba&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;cabc&amp;lt;/tex&amp;gt; || {{---}} || &amp;lt;tex&amp;gt;\langle 0, c \rangle &amp;lt;/tex&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;ac&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;ab&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;aba&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;abc&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;ab&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\langle 4, c\rangle &amp;lt;/tex&amp;gt; || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Результатом кодирования является список пар: &amp;lt;tex&amp;gt;\left[ \langle 0, a \rangle, \langle 0, b \rangle, \langle 1, c \rangle, \langle 1, b \rangle, \langle 4, a \rangle, \langle 0, c \rangle, \langle 4, c \rangle \right]&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Декодирование ===&lt;br /&gt;
&lt;br /&gt;
Декодирование происходит аналогично кодированию, на основе декодируемой информации строим словарь и берем из него значения.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''string''' decodeLZ78('''list&amp;lt;Node&amp;gt;''' encoded):&lt;br /&gt;
     '''list&amp;lt;string&amp;gt;''' dict = [&amp;quot;&amp;quot;]                        &amp;lt;font color=green&amp;gt;// словарь, слово с номером 0 {{---}} пустая строка&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''string''' ans = &amp;quot;&amp;quot;                                 &amp;lt;font color=green&amp;gt;// ответ&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''for''' node '''in''' encoded:&lt;br /&gt;
         word = dict[node.pos] + node.next           &amp;lt;font color=green&amp;gt;// составляем слово из уже известного из словаря и новой буквы&amp;lt;/font&amp;gt;&lt;br /&gt;
         ans += word                                 &amp;lt;font color=green&amp;gt;// приписываем к ответу&amp;lt;/font&amp;gt;&lt;br /&gt;
         dict.push(word)                             &amp;lt;font color=green&amp;gt;// добавляем в словарь&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''return''' ans&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Модификации ===&lt;br /&gt;
Одна из главных проблем &amp;lt;tex&amp;gt;\mathrm{LZ78}&amp;lt;/tex&amp;gt; {{---}} размер словаря. Он ничем не ограничен и может достигать огромных размеров на больших объемах входных данных. В различных модификациях установлены лимиты на размер словаря: при достижении определенного лимита словарь может «замораживаться» (в него перестают добавляться новые слова), из словаря могут удалять менее используемые или самые старые слова и так далее.&lt;br /&gt;
&lt;br /&gt;
Самой известной модификацией &amp;lt;tex&amp;gt;\mathrm{LZ78}&amp;lt;/tex&amp;gt; является [[Алгоритм LZW|LZW]]. В нём есть две важных особенности. Первая {{---}} словарь изначально инициализирован всеми символами алфавита. Вторая {{---}} после нахождения максимального префикса поиск следующего префикса начинается не с символа после неподходящего, а с самого неподходящего символа. Это позволяет не выводить неподходящий символ, а выяснять его прямо из словаря. Эта модификация используется в том числе в изображениях в формате &amp;lt;tex&amp;gt;\mathrm{GIF}&amp;lt;/tex&amp;gt;&amp;lt;ref&amp;gt;[https://en.wikipedia.org/wiki/GIF Wikipedia {{---}} GIF]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Алгоритм RLE]]&lt;br /&gt;
* [[Алгоритм LZW]]&lt;br /&gt;
* [[Алгоритм LZSS]]&lt;br /&gt;
* [[Алгоритм LZMA]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [https://en.wikipedia.org/wiki/LZ77_and_LZ78 Wikipedia {{---}} LZ77 and LZ78]&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/LZ77 Википедия {{---}} LZ77]&lt;br /&gt;
* [https://fenix.tecnico.ulisboa.pt/downloadFile/1407993358859638/Lempel_Ziv_by_Zeeh.pdf The Lempel Ziv Algorithm]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/data-compression/lz-2000 Визуализатор алгоритма LZ78]&lt;br /&gt;
* [http://compression.ru/download/articles/rev_univ/semenyuk_2001_econom_encoding.pdf Семенюк В.В. {{---}} Экономное кодирование дискретной информации]&lt;br /&gt;
* [http://mf.grsu.by/UchProc/livak/en/po/comprsite/theory_lz77.html Алгоритм LZ77]&lt;br /&gt;
* [http://www.binaryessence.com/dct/en000140.htm Lempel-Ziv-78]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Алгоритмы сжатия]]&lt;/div&gt;</summary>
		<author><name>178.94.18.98</name></author>	</entry>

	</feed>