文本打包算法

时间:2009-05-10 13:17:54

标签: algorithm text packing

我打赌有人之前已经解决了这个问题,但我的搜索结果是空的。

我想将一个单词列表打包到一个缓冲区中,跟踪每个单词的起始位置和长度。诀窍是我想通过消除冗余来有效地打包缓冲区。

示例:娃娃娃娃屋

这些可以简单地打包到缓冲区中dollhouse,记住doll是从位置0开始的四个字母,dollhouse是0处的九个字母,house是3的五个字母。

到目前为止,我想出的是:

  1. 将最长的单词排序为最短的:(娃娃屋,房子,洋娃娃)
  2. 扫描缓冲区以查看字符串是否已作为子字符串存在,如果是,请记下该位置。
  3. 如果它尚不存在,请将其添加到缓冲区的末尾。
  4. 由于长词通常包含较短的单词,因此效果很好,但应该可以做得更好。例如,如果我将单词列表扩展为包含ragdoll,那么我的算法会出现dollhouseragdoll,效率低于ragdollhouse

    这是一个预处理步骤,所以我并不十分担心速度。 O(n ^ 2)很好。另一方面,我的实际列表有数万个单词,所以O(n!)可能是不可能的。

    作为旁注,这个存储方案用于TrueType字体的`name'表中的数据,参见。 http://www.microsoft.com/typography/otspec/name.htm

8 个答案:

答案 0 :(得分:13)

这是最短的超字符串问题:找到包含一组给定字符串作为子字符串的最短字符串。根据{{​​3}}(您可能无法访问),解决此问题的确是 NP-complete 。但是,可以使用启发式解决方案。

作为第一步,您应该找到所有字符串作为其他字符串的子字符串并删除它们(当然您仍然需要以某种方式记录它们相对于包含字符串的位置)。使用this IEEE paper可以有效地找到这些完全包含的字符串。

然后,通过反复合并具有最长重叠的两个字符串,可以保证生成长度不小于最小可能长度的4倍的解。根据Zifre在generalised suffix tree上的评论建议,应该可以使用两个基数树快速找到重叠大小。或者,您可以以某种方式使用通用后缀树。

对不起,我无法为您找到一个不错的链接 - 似乎没有维基百科页面,或任何有关此特定问题的公开信息。简要提到Konrad Rudolph's answer,但没有提供建议的解决方案。

答案 1 :(得分:1)

我认为你可以使用Radix Tree。由于指向leafs和parent的指针,它需要一些内存,但很容易匹配字符串(O(k)(其中k是最长的字符串大小)。

答案 2 :(得分:1)

我首先想到的是:使用数据结构来确定字符串的公共前缀和后缀。然后在考虑这些前缀和后缀的情况下对单词进行排序。这会产生您想要的ragdollhouse

答案 3 :(得分:1)

看起来类似于Knapsack problem,它是NP完全的,因此没有“确定的”算法。

答案 4 :(得分:1)

我在大学做了一个实验室,我们的任务是实施一个简单的压缩程序。

我们所做的是将这些技术依次应用于文本:

  • BWT(Burrows-Wheeler transform):帮助将字母重新排序为相同字母的序列(提示*有数学替换以获取字母而不是实际进行旋转)
  • MTF(Move to front transform):将字母序列重写为动态列表的索引序列。
  • Huffman encoding:一种形式的熵编码构造一个可变长度的代码表,其中较短的代码被赋予经常遇到的符号,较长的代码被赋予不常见的符号

在这里,我找到了assignment page

要获取原始文本,您可以执行(1)霍夫曼解码,(2)逆MTF,然后(3)逆BWT。 Interwebs上有很多关于这一切的好资源。

答案 5 :(得分:1)

完善第3步。

  • 查看当前列表,查看列表中的任何单词是否以当前单词的后缀开头。 (您可能希望保留后缀长度超过某个长度 - 例如,长于1)。
  • 如果是,则将此单词的不同前缀添加为现有单词的前缀,并适当调整所有现有引用(慢!)
  • 如果不是,请在当前步骤3中将单词添加到列表末尾。

这将为您提供'ragdollhouse'作为示例中的存储数据。目前尚不清楚它是否总能最佳地发挥作用(例如,如果你在单词列表中也有'barbiedoll'和'dollar')。

答案 6 :(得分:0)

我再也不会重新发明这个轮子了。已经有大量的人力进入压缩算法,为什么不采用已有的算法呢?

以下是一些不错的选择:

  • gzip用于快速压缩/解压缩速度
  • bzip2有点压缩,但解压缩得慢得多
  • LZMA具有非常高的压缩比和快速解压缩(比bzip2快但比gzip慢)
  • lzop用于非常快速的压缩/解压缩

如果您使用Java,gzip is already integrated

答案 7 :(得分:0)

目前尚不清楚你想做什么。

您是否想要一种数据结构,让您以记忆意识的方式存储字符串,同时允许在合理的时间内进行搜索等操作?

你只是想要一个压缩的单词数组吗?

在第一种情况下,您可以选择patricia trie或String B-Tree。

对于第二种情况,你可以采用一些索引压缩技术,如:

如果你有类似的话:

aaa 
aaab
aasd
abaco
abad

你可以这样压缩:

0aaa
3b
2sd
1baco
2ad

该数字是前一个字符串的最大公共前缀的长度。 您可以调整该架构,例如。计划在K字之后“重启”公共前缀,以进行快速重建