变得更快

时间:2011-01-06 02:05:52

标签: algorithm diff

我正在研究扩展大型二进制文件。我已经实现了着名的Myers Diff算法,它可以产生最小的差异。但是,它是O(ND),所以为了区分两个非常不同的1 MB文件,我预计需要100万平方= 1万亿。那不好!

我想要的是一种产生潜在非最小差异的算法,但速度要快得多。我知道必须存在,因为Beyond Compare会这样做。但我不知道怎么做!

可以肯定:有像xdelta或bdiff这样的工具,但这些工具会产生一个用于计算机消耗的补丁,这与人类消耗差异不同。补丁涉及将一个文件转换为另一个文件,因此它可以执行诸如从文件的先前部分进行复制之类的操作。人类消耗品差异在那里可视地显示差异,并且只能插入和删除。例如,这个转换:

“puddi” - > “puddipuddipuddi”

会产生一个小小的“copy [0,4]到[5,9]和[10,14]”,但更大的差异是“追加'puddipuddi'”。我对产生较大差异的算法很感兴趣。

谢谢!

2 个答案:

答案 0 :(得分:4)

差异基本上与生物信息学中用于比对DNA序列的算法相同。这些序列通常很大(数百万或数十亿个核苷酸长),并且一个在较长基因组上运行良好的策略被程序MUMmer使用:

  1. 使用后缀树快速查找所有最大唯一匹配(两个文件中出现的子字符串以及无法在该条件下仍然保留的任何方向上扩展的子字符串)
  2. 使用增长最长的子序列动态规划算法快速找到两个文件中以连续顺序出现的最长MUM子集
  3. 将此MUM子集修复为对齐(即将这些区域标记为匹配)
  4. 如果认为有必要,在MUM间区域执行较慢(例如Myers)。在您的情况下,如果您发现最长MUM的长度低于某个阈值(您可能认为这两个文件不相关的证据),您可能会完全省略此步骤。
  5. 每当没有太多差异时,这往往会给出非常好的(尽管不是保证最优的)一组对齐区域(或等效地,一组非常小的差异)。我不确定每个步骤的确切时间范围,但我知道没有n^2或更高的术语。

    我相信MUMmer程序需要DNA或蛋白质序列,所以它可能不适用于你,但概念肯定适用于一般字符串(例如文件)所以如果你准备自己重新实现它我会推荐这种方法。

答案 1 :(得分:1)

从性能角度来看,随着文件大小的增长,GNU Diffutils可能是最强大的选择。对于你的情况,我可能会使用它side-by-side comparison format,这可能是这个地段最人性化的。但是,你不会以另一种格式取出它的输出并做一些工作来使它变得漂亮。

一个好的竞争者,其表现一直在稳步提升,包括无数次加速,是diff-match-patch。它以几种不同的语言实现Myers Diff算法,包括Java和JavaScript。有关后者的示例,请参阅online demo,其中包含漂亮的打印结果。如果你想对线路差异进行研究,请向wiki学习如何将其用于此目的的技巧。