【问题标题】:Detect largest suffix of some file that is prefix of another file检测某个文件的最大后缀是另一个文件的前缀
【发布时间】:2011-03-31 11:23:48
【问题描述】:

我有两个文件 - 我们称它们为 file0 和 file1。

我想要的是一个快速算法来解决以下问题(我很清楚如何编写一个相当慢的算法来解决它):

检测file0的最大后缀,即file1的前缀,即最大长度的内存块B(或者更准确地说:这样一个内存块的字节数)使得

  • file0 由一些内存块 A 组成,然后是 B
  • file1 由内存块 B 组成,后跟一些内存块 C

请注意,块 A、B 和 C 的长度也可以为零字节。

编辑(回答drysdam的评论):我想到的明显相当慢的算法(伪代码):让文件的长度以m为界,n与wlog m

for each length from m to 0
    compare the m last bytes of file0 with the first m bytes of file1
    if they are equal
        return length

这显然是一个 O(m*min(m, n)) 算法。如果文件大小相同,则为 O(n^2)。

我目前必须处理的文件大小为 10 到几百兆字节。但在极端情况下,它们的大小也可能为几 GB——大到不再适合 x86 的 32 位地址空间。

【问题讨论】:

  • 你的慢算法有多慢,你需要多快?我可以想到一种算法,但据我所知,它比你的“慢”算法慢。

标签: algorithm prefix


【解决方案1】:

考虑将您的字节视为数字 0..255,作为整数 mod p,其中 p 是素数,可以选择远大于 255。以下是计算 b0*x^2 + b1*x + b2 的两种方法:

(b0*x + b1)*x + b2

b0*x^2 + (b1*x + b2)。

因此,我可以通过从左到右计算这个数量来有效地计算这个数量 - 乘以 x 并添加 b2,或者通过从右到左计算 - 添加 b0*x^2。

选择一个随机 x 并在 AB 中从右到左计算,在 BC 中从左到右计算。如果计算的值匹配,则记下位置。稍后慢慢检查所有从最长开始的匹配项,看看 B 在两种情况下是否真的相同。

随机匹配的几率是多少?如果您有错误匹配,则 (a0 - c0)*x^2 + (a1 - c1)*x + (a2 - c2) = 0。 d 次多项式最多有 d 个根,所以如果 x 是随机的错误匹配的机会最多为 d / p,您可以通过将 mod p 用于适当大的 p 来使这个值变小。 (如果我没记错的话,有一个消息认证方案,其核心就是这个想法)。

【讨论】:

    【解决方案2】:

    根据您有多少可用内存,您可能需要考虑为第一个文件构建后缀树。一旦你有了这个,你可以查询与第二个文件的后缀最大重叠的第二个文件的前缀,方法是沿着与第二个文件前缀的字母匹配的边缘从根部向下遍历后缀树。由于后缀树可以在线性时间内构建,因此使用您的术语,此算法的运行时间为 O(|A| + |B|),因为构建后缀树需要 O(|A| + |B|) 时间O(|B|) 时间遍历后缀树找到块 B。

    【讨论】:

    • 这看起来是个好主意。较小文件大小的长度是线性的。
    • 如果您能提示如何处理后缀树“不再”适合内存的情况(因为 X86 上 32 位地址空间的限制),我完全满意。
    • 如果其中一个文件而不是另一个文件可以有一个适合内存的后缀树,您可以随时反转两个文件,为第二个文件构建一个后缀树,找到最长的后缀第一个文件是第二个文件的前缀。这行得通吗?
    • 我很清楚,您可以将自己限制为较小文件的大小。正如我在评论中所说:大多数文件“足够小”(10-几百 MB) - 但当它们的大小为几 GB 时它也应该工作。我认为为了处理这些文件,我将编写一个小型内存管理器,将后缀树的未使用部分交换到磁盘 - 这不是最快的方法,但可以完成它的工作。
    【解决方案3】:

    如果这不是学术任务,那么实施最简单的解决方案并查看它在您的数据上的表现可能是有意义的。

    例如,理论上更有效的基于 Knuth-Morris-Pratt 算法的解决方案可能比基于 IndexOf 的解决方案执行得更差(请参阅Overlap Detection)。

    对于大文件,您的程序可能一直在等待 I/O。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-28
      • 2010-09-05
      • 2019-06-25
      • 2019-09-19
      • 2017-01-23
      • 1970-01-01
      相关资源
      最近更新 更多