Skip to content

算法Algorithm

LZ77滑动窗口与重叠回指

LZ77 · LZ77 sliding-window decoding

用字面量和长度距离描述已输出历史,逐字节执行重叠复制,并区分匹配解析、token编码与解码成本。

形式陈述 ​

LZ77类编码把输入字节串解析成字面量和对已输出历史的回指。本页采用常见的二类token变体:Lit(b)直接输出字节 b;Match(ℓ,d)从当前位置向前距离 d 开始,连续复制长度 ℓ。窗口上限为 W,当前已输出长度为 p,合法回指满足

1≤d≤min(W,p),ℓ≥3.

长度下限3是本教学解析器的约定,不是所有LZ变体的定义。编码端还限定最大匹配长 Lmax。解码语义按从小到大的 i=0,…,ℓ−1 执行

out[p+i]=out[p+i−d].

当 ℓ>d 时,右侧有些位置是这个token刚刚生成的字节。它们已经存在,因此依然合法。实现可写成重复 ℓ 次“读取当前 out[-d],追加到末尾”。不能在复制前只截取一份历史子串,再误以为它已有 ℓ 字节。

给定token和足够的输出容量,解码结果由上述转移唯一确定。编码解析却可能有多种选择:发字面量、使用短匹配或长匹配,都可能恢复同一个原文;不同解析的bit费用要由后续token编码决定。

直觉

距离回答“回头多少格”,长度回答“往前写多少格”。回头的位置不是固定快照,而是随写指针一起前移。于是一个短周期就可以自我扩展:历史里只有AB,也足以再生出ABABABA。

编码器需要找匹配,解码器只需要按已经给出的指针复制。找最长匹配属于字符串匹配问题;不能把编码端可能昂贵的搜索成本加到每次解码的定义里,也不能把解码的简单性反过来当作免费搜索算法。

回指读取含本次刚写入的历史
例子与边界

窗口 W=8、最大匹配18的教学贪心解析器,将 ABABABABA 编成 Lit(A), Lit(B), Match(7,2)。读入两个字面量后,p=2:

  • 写位置2,从0读A;输出ABA
  • 写位置3,从1读B;输出ABAB
  • 写位置4,从2读A;这个A是第一步刚写入的
  • 写位置5、6、7、8,分别从3、4、5、6读B、A、B、A

最后输出九字节 ABABABABA。一次性复制原历史切片 out[0:7] 只能拿到AB,无法实现这个token。若一概拒绝 ℓ>d,就会拒绝本来合法且很有用的重叠回指。

距离0没有本页定义的历史源,必须拒绝。输出还为空时,任何正距离都无效。已有一个字节时距离2也无效;“它还在文件中某处”并不等于“已经解出并在窗口中”。空文件用空token序列得到空输出,停止方式由外层格式规定。对单字母长串可以发一个A,再用距离1的匹配扩展。

长度与距离还需要编码成bit。例如DEFLATE把长度11表示为长度符号265加1个扩展bit,基值11,扩展值0;距离6表示为距离符号4加1个扩展bit,基值5,扩展值1。总费用是两个符号各自的Huffman码长再加2bit,不能仅数“一个匹配token”。本单元只复算这项参数映射,不输出DEFLATE块。

推论与应用

复制为何唯一且保持原文 ​

对匹配内的位置 i 归纳。因为 d≥1,源位置 p+i−d 严格早于目标位置 p+i;它要么来自此前token,要么已由更小的 i 写好。编码端只有验证原文满足对应的周期匹配才可输出该token,解码端依次复制就保持每个位置与原文相同。重叠不会引入循环依赖。

用朴素搜索在每个输入位置尝试至多 W 个距离、每个比较至多 Lmax 字节,编码上界为 O(nWLmax);后缀结构或哈希匹配可改变这个成本。解码按上述算法每写一字节花常数操作,若有 k 个token、展开长度为 n,工作为 O(k+n)。只需保留最近 W 字节时可流式输出,工作历史为 O(W);检查器返回整个结果,因而还占 O(n) 输出空间。

贪心最长匹配减少当前位置的未处理字节数,不自动最小化最终bit数:更长匹配可能需要昂贵的长度或距离符号,也可能错过下一位置更省的匹配。若要证明最优解析,需要把token费用和未来状态写进优化问题。

回指长度来自不可信文件时,先检查 ℓ≤Nmax−p 和剩余工作预算,再执行复制;不要先分配 ℓ 大小的临时数组。这项资源契约在有界解压中与码表、字典预算统一。

参考资料
  • L. Peter Deutsch,RFC1951,§2、§3.2.3:LZ77式长度/距离与允许重叠的复制;§3.2.5:长度及距离的基值/扩展位表;§§3.2.6–3.2.7:Huffman块模式
  • 本单元检查器:朴素确定性解析、逐字节复制,以及从周期种子生成整段的独立复算
关系图谱7 个相邻概念 · 2 类关系

拖动节点调整位置。

显示关系

显示:依赖

  1. 前置三跳
  2. 前置二跳
  3. 前置一跳
  4. 当前条目
  5. 后续一跳
  6. 后续二跳
  7. 后续三跳
文字版关系按与当前条目的最短距离分组
类型化关系

使用的工具

被这些条目使用