Главная > Сжатие данных, изображений и звука
НАПИШУ ВСЁ ЧТО ЗАДАЛИ
СЕКРЕТНЫЙ БОТ В ТЕЛЕГЕ
<< Предыдущий параграф Следующий параграф >>
Пред.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
След.
Макеты страниц

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

Также, советуем воспользоваться поиском по сайту, мы уверены, что вы сможете найти больше информации по нужной Вам тематике

ДЛЯ СТУДЕНТОВ И ШКОЛЬНИКОВ ЕСТЬ
ZADANIA.TO

2.3. LZ78

Метод LZ78 (иногда его называют LZ2, см. [Ziv 78]) не использует буфер поиск, упреждающий буфер и скользящее окно. Вместо этого имеется словарь встретившихся ранее строк. В начале этот словарь пуст (или почти пуст), и размер этого словаря ограничен только объемом доступной памяти. На выход кодера поступает последовательность меток, состоящих из двух полей. Первое поле - это указатель на строку в словаре, а второе код символа. Метка не содержит длины строки, поскольку строка берется из словаря. Каждая метка соответствует последовательности во входном файле, и эта последовательность добавляется в словарь после того, как метка записана в выходной сжатый файл. Ничего из словаря не удаляется, что является одновременно и преимуществом над LZ77 (поскольку будущие строки могут совпадать даже с очень давними последовательностями) и недостатком (так как быстро растет объем словаря).

Словарь начинает строиться из пустой строки в позиции нуль. По мере поступления и кодирования символов, новые строки добавляются в позиции 1, 2 и т.д. Когда следующий символ  читается из входного файла, в словаре ищется строка из одного символа . Если такой строки нет, то  добавляется в словарь, а на выход подается метка . Эта метка означает строку «нуль » (соединение нулевой строки и ). Если вхождение символа  обнаружено (скажем, в позиции 37), то читается следующий символ , и в словаре ищется вхождение двухсимвольной строки . Если такое не найдено, то в словарь записывается строка , а на выход подается метка . Такая метка означает строку , так как позицию 37 в словаре занимает символ . Процесс продолжается до конца входного файла.

В общем случае текущий символ читается и становится однобуквенной строкой. Затем кодер пытается найти ее в словаре. Если строка найдена, читается следующий символ и присоединяется к текущей строке, образуя двухбуквенную строку, которую кодер опять пытается найти в словаре. До тех пор пока такие строки находятся в словаре, происходит чтение новых символов и их присоединение к текущей строке. В некоторый момент такой строки в словаре не оказывается. Тогда кодер добавляет ее в словарь и строит метку, в первом поле которой стоит указатель на последнюю найденную в словаре строку, а во втором поле записан последний символ строки (на котором произошел обрыв успешных поисков). В табл. 2.4 показаны шаги при декодировании последовательности «sir_sid_eastman_easily_teases_sea_sick_seals».

Словарь

Метка

Словарь

Метка

0 null

 

 

 

1 «s»

(0,«s»)

14 «y»

(0, «y»)

2 «i»

(0,«i»)

15 «_t»

(4,«t»)

3 «r»

(0,«r»)

16 «e»

(0,«е»)

4 «_»

(0,«_»)

17 «as»

(8,«s»)

5 «si»

(1,«i»)

18 «es»

(16,«s»)

6 «d»

(0,«d»)

19 «_s»

(4,«s»)

7 «_e»

(4, «e»)

20 «ea»

(4,«а»)

8 «а»

(0,«а»)

21 «_si»

(19,«i»)

9 «st»

(l,«t»)

22 «c»

(0,«с»)

10 «m»

(0,«m»)

23 «k»

(0,«k»)

11 «an»

(8,«n»)

24 «_se»

(19,«е»)

12 «_еа»

(7,«а»)

25 «al»

(8,«l»)

13 «sil»

(5, «l»)

26 «s(eof)»

(l,«(eof)»)

Табл. 2.4. Шаги кодирования LZ78.

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

Хорошей структурой для организации словаря является дерево, но не двоичное. Дерево начинается нулевой строкой в корне. Все строки, начинающиеся с нулевой строки (строки, для которых указатель в метке равен нулю), добавляются к дереву как потомки корня. В нашем примере таковыми служат следующие строки: s, i, r, _, d, a, m, у, е, с, k. Все они становятся корнями поддеревьев, показанных на рис. 2.5. Например, все строки, начинающиеся с символа s (четыре строки si, sil, st и s(eof)) образуют поддерево узла s.

В 8-битовом алфавите имеется всего 256 различных символов. В принципе, каждый узел дерева может иметь до 256 потомков. Следовательно, добавление новых узлов на дерево является динамическим процессом. Когда узел будет создаваться, у него еще нет потомков, поэтому необходимо зарезервировать некоторый объем памяти для них. Поскольку удалять узлы с дерева не придется, не придется и заниматься перераспределением памяти, что несколько упрощает манипулирование с ней.

090.jpg

Рис. 2.5. Словарное дерево для LZ78.

На таком дереве очень легко искать строки и добавлять новые символы. Например, чтобы найти строку sil, программа ищет символ s в корне, затем его потомка i символа s, и так далее, спускаясь вниз по дереву. Вот еще некоторые примеры.

1. Когда символ s из sid появляется на входе при шаге 5, кодер находит узел «1-s» на дереве как потомка «null». Затем поступает символ i, но узел s не имеет такого потомка (у него в этот момент вовсе нет потомков). Тогда кодер добавляет узел «5-i» в виде потомка узла «1-s», что означает добавление на дерево строки si.

2. Когда на входе появляется пробел между eastman и easily на шаге 12, возникает похожая ситуация. Кодер обнаруживает узел «4-_», получает символ е, находит «7-е», получает а, но у «7-е» нет потомка а, поэтому он добавляет узел «12-а», что эквивалентно добавлению строки «_еа».

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

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

1. Простейшее решение это заморозить словарь, когда он переполнится. Новые узлы не добавляются, словарь становится статическим, но с его помощью можно по-прежнему кодировать последовательности.

2. Удалить все дерево при переполнении и начать строить новое. Это решение эффективно разбивает данные на блоки, и в каждом блоке используется свой собственный словарь. Если содержимое сжимаемых данных меняется от блока к блоку, то этот метод дает хорошие результаты, поскольку в словаре не хранятся строки, которые с малой вероятностью поступят в дальнейшем. Здесь опять, как и в LZ77 неявно предполагается, что похожие данные будут группироваться близко друг к другу.

3. Утилита compress операционной системы UNIX использует более сложное решение. Эта программа (еще называемая LZC) использует алгоритм LZW (см. § 2.4) с растущим словарем. Она начинает работать с маленьким словарем, состоящим всего из  строк, причем первые 256 уже заполнены. При использовании исходного словаря в сжатый файл записываются 9-битовые указатели. После заполнения этого словаря его размер удваивается до 1024 строк. С этого момента используются 10-битовые указатели. Этот процесс продолжается до тех пор, пока размер указателей не достигнет некоторого максимального значения, задаваемого пользователем (от 9 до 16 бит, причем 16 принято по умолчанию). Когда наибольший допустимый словарь полностью заполняется, программа продолжает работать без изменения словаря (который теперь становится статическим), но одновременно делается мониторинг коэффициента сжатия. Если этот коэффициент превышает некоторый предустановленный порог, то происходит сброс словаря, процесс начинается с исходного 512-строчного словаря. При таком подходе словарь никогда не устаревает.

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

Декодер LZ78 работает примерно так же, как и кодер, строя словарь и оперируя с ним. Поэтому он более сложен, чем декодер LZ77.

Эти слова! Как невинно и беспомощно они выглядят в проявляют в руках тех, кто умеет объединять их.
- Натаниэль Хаусорн

 

1
Оглавление
email@scask.ru