基本上,我正在做计算机科学的IB扩展论文,并且正在考虑使用LZW算法的非贪婪实现。我找到了以下链接:
并且一直在假设论文1中描述的算法和论文2中的LZW-FP基本相同的前提下进行操作。无论哪种方式,在论文1中跟踪伪代码都是一种痛苦的经历,但是却一无所获,用我的老师的话说,“难以理解。”如果任何人都可以弄清楚如何跟踪它,或者碰巧曾经研究过该算法并知道它是如何工作的,那将是一个很大的帮助。
答案 0 :(得分:3)
注意:我将“纸张1”称为Horspool 1995,将“纸张2”称为Matias et al 1998。我只看过Horspool 1995中的LZW算法,因此,如果您指的是LZSS算法,那对您没有太大帮助。
我的理解是,Matias等人1998年的作者称Horspool算法为“ LZW-FPA”,这与他们所说的“ LZW-FP”不同;差异与算法决定要添加到字典中的子字符串的方式有关。由于“ LZW-FP”将与LZW添加的完全相同的子字符串添加到字典中,因此LZW-FP无法为任何字符串产生更长的压缩序列。 LZW-FPA(和Horspool的算法)在每个输出周期添加贪婪匹配的后继字符串。那不是相同的子字符串(因为贪婪的匹配不会像在LZW中那样开始于同一点),因此从理论上讲,它可能会产生比LZW更长的压缩序列。
Horspool的算法实际上非常简单,但是它受到这样一个事实的困扰,即所提供的伪代码中存在一些愚蠢的错误。实现算法是检测和修复这些错误的好方法。我在下面放了一个带注释的伪代码版本。
类似于LZW的算法将输入分解为一系列块。压缩器维护可用块的字典(以及相关的代码字)。最初,字典包含所有单字符字符串。然后,它逐步遍历输入,在每个点上找到字典中该点处的最长前缀。找到该块后,它将输出其代码字,并将添加了下一个输入字符的块添加到字典中。 (由于找到的块是词典中最长的前缀,因此该块加上下一个字符不能在词典中。)然后,它越过该块,并继续到下一个输入点(恰好在字典的最后一个字符之前)。阻止它刚添加到字典中。)Horspool的修改还找到了每个点上最长的前缀,并将该前缀扩展了一个字符到字典中。但是它不会立即输出该块。取而代之的是,它考虑贪婪匹配的前缀,并为每个匹配确定下一个贪婪匹配的含义。这使它具有两个块的候选范围;它选择最先进的程度。为了避免在此搜索中花费过多的时间,在假设较短的前缀不太可能产生较长范围的前提下,通过将要测试的前缀数量对算法进行参数化。 (尽管您可能想通过自己的实验来验证这一点,但Horspool为这种启发式方法提供了一些证据。)
在Horspool的伪代码中,α是我所谓的“候选匹配”-即在上一步中找到的贪婪匹配-β j 是输入的贪婪后继匹配α的第j 前缀之后的点。 (从头算起,所以β 0 恰好是α的贪心后继匹配,结果是将K设置为0将产生LZW算法。我认为Horspool在某个地方提到了这一事实。)L是只是α的长度。该算法最终将使用某个前缀α(可能是(通常)全部)。
这是图2中带有我的注释的Horspool伪代码:
initialize dictionary D with all strings of length 1;
set α = the string in D that matches the first
symbol of the input;
set L = length(α);
while more than L symbols of input remain do
begin
// The new string α++head(β0) must be added to D here, rather
// than where Horspool adds it. Otherwise, it is not available for the
// search for a successor match. Of course, head(β0) is not meaningful here
// because β0 doesn't exist yet, but it's just the symbol following α in
// the input.
for j := 0 to max(L-1,K) do
// The above should be min(L - 1, K), not max.
// (Otherwise, K would be almost irrelevant.)
find βj, the longest string in D that matches
the input starting L-j symbols ahead;
add the new string α++head(β0) to D;
// See above; the new string must be added before the search
set j = value of j in range 0 to max(L-1,K)
such that L - j + length(βj) is a maximum;
// Again, min rather than max
output the index in D of the string prefix(α,j);
// Here Horspool forgets that j is the number of characters removed
// from the end of α, not the number of characters in the desired prefix.
// So j should be replaced with L - j
advance j symbols through the input;
// Again, the advance should be L - j, not j
set α = βj;
set L = length(α);
end;
output the index in D of string α;