【问题标题】:compressed string storage压缩字符串存储
【发布时间】:2011-05-19 15:31:18
【问题描述】:

假设我有很多包含非平凡长度字符串的对象(大约 3-4kb)。这些字符串彼此不同,但同时包含许多共同的部分/子序列。平均而言,任何单个字符串的 80-90% 也包含在其他字符串中。有没有一种简单的方法可以自动利用这种巨大的冗余来压缩数据?
理想情况下,解决方案是 C++ 并且对用户透明(即,我可以像访问常规只读 const std::string 而是从压缩存储中读取一样使用它)。

【问题讨论】:

  • 字符串如何有共同的子序列。这是因为重复编辑还是数据重合?
  • 想象一下不支持 CSS 的静态 HTML。您有很多多余的 html,只有很少的更改部分包含实际信息。
  • 1GB 的内存可以容纳大约 100,000 个大小为 3-4KB 的未压缩 blob。你真的需要它来适应更少吗?
  • 是的。我正在处理 >= 500.000,这只是数据的一部分(在 32 位应用程序中......)。

标签: c++ algorithm string data-structures compression


【解决方案1】:

就像@Saeed 提到的那样,简单的霍夫曼编码在这里会表现良好。

字典中没有必要,如果常用词是先验已知的(你提到它是一个 HTML)。只需使用来自许多 HTML 文件的统计数据预先计算一个霍夫曼表(请注意,您可以使用单个符号对整个标签进行编码,并且您可以拥有任意数量的符号)。

【讨论】:

    【解决方案2】:

    如果字符串的公共部分是通用的,因为它们是由其他字符串组成的,那么您可能会通过使用 stlport rope 类获得一些牵引力,它像 std::string 一样查找所有世界,但是使用子字符串树表示和写入时复制,这使得它们既非常节省空间(共享公共子字符串),又非常擅长插入和删除(log(n))

    何时使用绳子:

    • 您正在制作模板引擎。文档实例是通过替换模板中的不同数据从模板生成的,然后缓存以备将来使用。模板和实例共有的部分只存储一次并在实例之间共享,插入和删除都很便宜。

    何时不使用绳子:

    • 您正在从应用程序域外(从磁盘或通过网络)加载许多文档,并且无需修改即可使用它们。如果没有将字符串从一根绳索复制到另一根绳索,则绳索不会共享字符串。如果您负担得起找到公共子字符串的工作,那么仍然可以使用绳索来改进您的最终表示。

    【讨论】:

    • 我认为它不仅仅是写时复制。我认为数据存储在字符串树中,而不是在连续的内存区域中。
    • 它是写时复制结合了以与附加到字符串相同的算法成本预先添加到字符串的能力。
    • 我想我适合你的第二种情况:我的字符串不受我控制,我从数据库中获取它们。
    【解决方案3】:

    你可以使用huffman coding 实现并不难,还有语言(如C#和java)中的zip算法,你可以使用它们。

    另外如果你确定 80-90% 全部重复,创建一个所有单词的字典,然后为每个字符串存储字典单词的位置,意味着有一个大尺寸的位数组(10000 ie)并标记相关如果当前字符串中存在words[i],则将bits[i] 定位到1。认为每个字长是 5 个字符,那么缩写大约需要 1/5 大小。

    【讨论】:

      【解决方案4】:

      从算法上讲,Lempel–Ziv–Welch 为所有对象/字符串提供一个字典可能是一个好的开始。

      【讨论】:

      • 如果随着时间的推移动态创建很多字符串,这个字典会变大。所以最后,只用 LZW 单独压缩字符串可能是一个更简单更好的主意。
      • 加载初始批次后创建的字符串将非常少,所以我不认为会有问题......
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-25
      • 1970-01-01
      • 2011-08-18
      • 2015-12-14
      相关资源
      最近更新 更多