繁体   English   中英

文字打包算法

[英]Text packing algorithm

我敢打赌,以前有人解决过这个问题,但我的搜索却空了。

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

示例:洋娃娃洋娃娃屋

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

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

  1. 排序最长到最短的单词:(娃娃屋,房子,娃娃)
  2. 扫描缓冲区以查看字符串是否已经作为子字符串存在,如果有,请记下位置。
  3. 如果尚不存在,请将其添加到缓冲区的末尾。

由于长词通常包含较短的词,因此效果很好,但是应该可以做得更好。 例如,如果我扩展单词列表以包括ragdoll,则我的算法将使用dollhouseragdoll ,这比ragdollhouse效率低。

这是一个预处理步骤,因此我不必担心速度。 O(n ^ 2)可以。 另一方面,我的实际列表中有成千上万个单词,因此O(n!)可能是不可能的。

附带说明,此存储方案用于TrueType字体的“名称”表中的数据,请参见。 http://www.microsoft.com/typography/otspec/name.htm

这是最短的超字符串问题 :找到包含一组给定字符串作为子字符串的最短字符串。 根据这份IEEE论文 (不幸的是,您可能无法获得),准确地解决此问题是NP-complete 但是,可以使用启发式解决方案。

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

然后,通过重复合并重叠时间最长的两个字符串,可以确保生成长度不小于最小可能长度的4倍的解决方案。 正如Zifre对Konrad Rudolph的回答的评论所建议的那样,应该可以通过使用两个基数树快速找到重叠大小。 或者,您也许可以以某种方式使用广义后缀树。

抱歉,我无法为您找到一个体面的链接-似乎没有Wikipedia页面,或有关此特定问题的任何可公开访问的信息。 尽管未提供建议的解决方案,但在此简要提及。

我认为您可以使用基数树 由于指向叶子和父级的指针会花费一些内存,但是很容易匹配字符串(O(k)(其中k是最长的字符串大小)。

我的第一个想法是:使用数据结构来确定字符串的常见前缀和后缀。 然后对考虑这些前缀和后缀的单词进行排序。 这将导致您需要的ragdollhouse

看起来类似于背包问题 ,它是NP完全的,因此没有“确定性”算法。

我在大学里做了一个实验室,在那里我们负责实施一个简单的压缩程序。

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

  • BWT( Burrows-Wheeler变换 ):有助于将字母重新排序为相同字母的序列(提示*有数学上的替换方式,可获取字母而不是实际进行旋转)
  • MTF( 移至最前转换 ):将字母序列重写为动态列表的索引序列。
  • 霍夫曼编码(Huffman encoding) :一种熵编码形式,用于构建可变长度代码表,其中将较短的代码分配给经常遇到的符号,将较长的代码分配给不经常遇到的符号

在这里,我找到了作业页面

要取回原始文本,请执行(1)Huffman解码,(2)逆MTF,然后(3)逆BWT。 在Interwebs上,所有这些都有很多很好的资源。

优化步骤3。

  • 浏览当前列表,查看列表中是否有任何单词以当前单词的后缀开头。 (例如,您可能希望后缀的长度大于某个长度,例如大于1)。
  • 如果是,则为该单词添加不同的前缀作为现有单词的前缀,并适当调整所有现有参考(慢!)
  • 如果否,请按照当前步骤3在列表末尾添加单词。

这将为您提供“ ragdollhouse”作为示例中的存储数据。 尚不清楚它是否始终会保持最佳状态(例如,如果单词列表中还包含“ barbiedoll”和“ dollar”)。

我不会再发明这个轮子了。 压缩算法已经投入了大量的人力,为什么不采用一种可用的压缩算法呢?

这里有一些不错的选择:

  • gzip提供快速压缩/解压缩速度
  • bzip2压缩有点痛苦,但解压缩慢得多
  • LZMA具有很高的压缩率和快速解压缩(比bzip2快,但比gzip慢)
  • lzop可以非常快速地进行压缩/解压缩

如果您使用Java, 则已经集成了gzip

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

您是否想要一个数据结构,让您以内存意识方式存储字符串,同时在合理的时间内使诸如搜索之类的操作成为可能?

您是否只需要压缩的单词数组?

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

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

如果您有类似的东西:

aaa 
aaab
aasd
abaco
abad

您可以像这样压缩:

0aaa
3b
2sd
1baco
2ad

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM