基于重复的,基于模式的数据压缩算法

时间:2012-04-19 01:53:34

标签: algorithm data-compression

假设我有以下字符串:

ABCADCADCADABC

我想通过查找重复的子串来压缩它。 什么算法能提供最佳压缩效果?

在上面的示例中,它应该返回

AB*1 CAD*3 ABC*1

为了进行比较,贪婪算法可能会返回

ABC*1 ADC*2 AD*1 ABC*1

4 个答案:

答案 0 :(得分:3)

根据您是喜欢快速,简单还是高压缩比,您可以查看Lempel-Ziv-Welch (LZW)Lempel-Ziv-Markov chain (LZMA)算法。他们都保留了重复字符串的字典。

答案 1 :(得分:3)

这听起来像是后缀数组/树的作业!

http://en.wikipedia.org/wiki/Suffix_array

您可以使用在字符串上构建的后缀数组来确定重复的模式。例如,我们可以在你的例子中构建一个后缀数组,如下所示(我总是在每个字母之后使用$,你可以对它进行排序,以便$在每个字母之前出现......任何一种方式都可以工作):

ABCADCADCADABC$
ABC$
ADABC$
ADCADABC$
ADCADCADABC$
BCADCADCADABC$
BC$
CADABC$
CADCADABC$
CADCADCADABC$
C$
DABC$
DCADABC$
DCADCADABC$
$

由此,我们可以更容易地看到字符串中的常见模式。使用此后缀数组表示中的信息,我们可以看到CAD在局部区域重复3次,我们可能会使用它作为压缩的选择。 ADC和DCA等不那么吸引人,因为它们压缩的字符串较少。

http://en.wikipedia.org/wiki/Suffix_tree

后缀树是执行相同任务的更有效方法。一旦你围绕如何使用后缀数组做一些事情,那么进入后缀树并不是太过分了。实际上,这用于流行的压缩算法,包括LZW 1和BWT(Bzip)2

答案 2 :(得分:2)

它可能没有实际意义,但对于您要求的特定问题,有一个动态编程解决方案。如果您已经计算出从第一个字符开始压缩长度为1,2,3 ... n-1的字符串的最佳方法,那么您可以计算从第一个字符开始压缩长度为n的字符串的最佳方法查看每种可能性k的最后k个字符,看看它们是否构成简单字符串的倍数。如果是这样,计算压缩前n个k字符的成本,然后使用字符串的倍数表示最后的k个字符。

所以在你的例子中,你会注意到ABC是自身的倍数,如果你把它表达为ABC * 1,你可以使用你已经为AB CAD *的前11个字符制定的答案3产生AB * 1 CAD * 3 ABC * 1

答案 3 :(得分:1)

更好的是:

ABCAD(6,3)(3,11)

其中(n,d)是匹配的长度和距离。所以(6,3)从三个字节开始复制六个字节。虽然这听起来有点奇怪,但是当它进入三个字节时,它需要的下三个字节已被复制。因此附加CADCAD。 (3,11)导致ABC被追加。

这称为LZ77压缩。它是由zip,gzip和zlib使用deflate压缩数据格式实现的。该格式不仅引用了先前的字符串匹配,还对文字(例如ABCAD)以及长度和距离使用了霍夫曼压缩。