“滑动历史最长匹配把编码端搜索具体化:在完整输入的后缀索引上维护会到期的活动秩,只比较两个活动字典序邻居即可求最长长度及见证。这个见证不保证距离最短;固定位费用最优解析再按距离与长度的价格档保…”
七个A,只需一个字面量加一次长回指,看上去已经很省。可是如果“长度6”本身比两次“长度3”贵,这个最少token的方案仍会多花一位。最优解析必须先说明在优化什么:同一份原文可以有很多token序列,只有码制固定以后,比较它们的bit总数才有确定答案。
形式陈述
先把价格写死
输入为字节串 Match(ℓ,d)须满足
本页规定如下二进制payload,不包含外层文件头:
| token | 从左到右的比特 | 位数 |
|---|---|---|
Lit(b) |
0,随后8位字节b |
9 |
Match(ℓ,d) |
1,随后 |
对正整数
解码时先数0,遇到第一个1后再取相同数目的后续位,得到该整数。两个整数码不需要分隔符;token首位又区分字面量和匹配。所有费用只依赖本token的长度、距离或字节,不会因先前token频数改变。这项条件是下面一维状态成立的关键。
optimal_parse(T,W,C)返回最小有效位数、一个达到它的token序列、全部后缀费用及恢复选择。相同位置的并列最优解不要求唯一:公开实现先选字面量,只在严格更省时替换,再按距离档、长度档顺序保留第一个胜者。
为什么只记当前位置就够
利用动态规划的状态充分性与反向求值,定义
位置
从右到左求值。每个候选确实是一段合法token再接合法后缀,因此不会给出虚假低价;任取最优解析,其首token必在这些候选中,剩余部分若不是对应位置的最优后缀,就能替换得更省。两向论证给出递推正确性。[1, §5]
直接枚举所有距离和长度还很贵。接下来省的是检查转移的工作,并没有删掉某些合法长度。
距离档给一个最长见证
按
只保留非空档。该档所有距离的码长都是
某个长度
长度档变成一次区间最小值
对
例如
把已算好的 Match(x-p,p-q_k[p]),不需要为每个长度再查一个来源。
D[n] = 0; 其余位置暂存 infinity = 9n+1
for p = n-1 .. 0:
best = 9+D[p+1]; choice = Lit(T[p])
for each nonempty distance band k:
M,q = precomputed_match[k][p]
for each length-cost interval [L,U] clipped to [3,M]:
suffix_bits,x = tree.minimum(p+L,p+U+1)
candidate = 3+2k+2j+suffix_bits
if candidate < best:
best = candidate; choice = Match(x-p,p-q)
D[p] = best; save choice; tree.assign(p,best)
查询时所有目的位置都大于
直觉
原递推像一张很密的价目表:每个距离、每个长度都写一行。同一个距离价格档内,来源是哪一个不重要,只要能复制所选长度;同一个长度价格档内,token价格也不变,差别全在落脚位置之后还要付多少。
于是先问“这个价格档最远能复制多长”,再问“允许的落脚区间中哪一格后续最便宜”。线段树没有替我们证明最优性,它只快速回答第二个问题。若遗漏一个价格变化点,或者把区间端点写错一格,再快的查询也只是在高效计算错误递推。
例子与边界
七个A:少一个token,却多一位
取 Lit(A),再用距离1一次复制长度6。费用为
而 Lit(A), Match(3,1), Match(3,1) 花
| p | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|---|
| 15 | 6 | 5 | 5 | 3 | 18 | 9 | 0 |
在
逐位编码结果可以直接核查:
贪心:001000001 | 1001001 共16位,payload十六进制20c9
最优:001000001 | 111 | 111 共15位,补1个0后十六进制20fe
两份payload都占2个物理字节。结论是一位有效payload的节省,不是一字节文件大小的节省,更未计入外层元数据。
最长见证不能跨价档复用
前页 ABAABABA 在
空输入与模型变化
空串的答案为0位、空token与空payload。
即使正文相同,若后续码价会随token频数、字典状态、分块选择或前一个距离改变,仅有
推论与应用
从选择恢复token,再恢复字节
每位置保存的选择都达到
公开 encode_tokens校验token结构、窗口、长度和总展开长度,输出有效位串、有效位数和补零打包的十六进制payload;它不拿一个未提供的原文验证token内容。对解析器产生的token,正确性由上面的匹配见证保证,再以实际解码比较原文复核。
解码函数采用有界解压的先验预算检查:先核验声明输出长度、有效位数、实际payload字节数和末尾零填充,再读token。gamma的前导零计数也受本次允许最大值的位长约束;距离不得超过已经输出的窗口,长度不得超过上限或剩余输出,所有检查在复制之前完成。最后必须恰好用完有效位,尾随有效位不能被静默忽略。
这只是一个有外部参数的payload接口。接收方仍需被明确告知
真实算法账单
令
后缀预处理花
公开实现保存全部距离档的
若payload有
Ferragina等人的算法对其指定费用模型进一步压缩候选并达到更强的时间空间界。本页保留所有长度区间,用较直接的距离档扫描与树查询,明确支付上述对数因子;最小匹配长3也要求谨慎处理被截短至1或2的候选,不能不经证明搬用别的稀疏化规则。[1]
完整终点任务要求把活动历史、位价递推、token恢复和预算拒绝串成可重复的执行证据,而不只给一个“比贪心更省”的数字。
参考资料
- [1] Paolo Ferragina, Igor Nitto and Rossano Venturini, On the Bit-Complexity of Lempel-Ziv Compression, SIAM Journal on Computing 42(4), 2013, pp. 1521–1541,DOI 10.1137/120869511。§2 的允许重叠变体,§3 的费用问题,§5 的最短路表述,§5.2 的等距离费用窗口。本文固定了自己的token语法并给出独立区间完备性证明,没有声称实现论文的最强界。
- [2] Peter Elias, Universal Codeword Sets and Representations of the Integers, IEEE Transactions on Information Theory 21(2), 1975, pp. 194–203,§V,印刷页199的
排列与 码长。这里仅使用该整数表示,不借此宣称整份压缩结果具有通用最优性。 - [3] L. Peter Deutsch, RFC1951, §§3.2.5–3.2.7:DEFLATE的长度/距离扩展位和固定、动态Huffman块模式,与本文固定gamma-payload区分。