Eugene Myers的Diff算法:找到“A”和“B”的最长公共子序列

时间:2015-04-14 20:45:53

标签: algorithm diff

我一直在审核Eugene Myers' Diff Algorithm Paper。这是在流行的diff程序中实现的算法。

在论文的第12页,它提供了算法的伪代码,用于查找AB的最长公共子序列:

LCS(A, N, B, M)
    If N > 0 and M > 0 Then
        Find the middle snake and the length of an optimal path for A and B.
        Suppose it is from (x, y) to (u, v).
        If D > 1 Then
            LCS(A[1..x], x, B[1..y], y)
            Output A[x+1..u]
            LCS(A[u+1..N], N-u, B[v+1..M], M-v)
        Else If M > N Then
            Output A[1..N].
        Else
            Output B[1..M].

假设A =" A"和B =" B"。在这种情况下,N = 1且M = 1.中间蛇将是(x,y)=(0,1)和(u,v)=(0,1),因为没有对角线。在这种情况下,D = 1,因为算法只采取了一个步骤。

该算法表示在这种情况下唯一要做的是Output B[1..M],等于&#34; B&#34;,因为N&gt; 0,M> 0,D = 1,M = N.但这似乎是错误的,因为在&#34; A&#34;之间没有共同的子序列。和&#34; B&#34;。该论文的评论是,如果D <= 1则通过删除或插入至多一个符号来从A获得B&#34;是不正确的,因为&#34; A&#34;必须删除&#34; B&#34;加入。

我在这里误解了什么?

1 个答案:

答案 0 :(得分:7)

你误解了D-path和snake的定义。

从第4页开始:

  

让D路径成为从(0,0)开始的具有正好D非对角线的路径   边缘。 0路径必须仅由对角线边缘组成。通过简单的归纳,D路径必须由(D-1)路径和非对角线边缘组成,然后可能为空的对角线边缘序列称为蛇 < / p>

因此,在A =“A”且B =“B”的示例中,最佳路径是2路径(一条水平路径和一条垂直路径),中间的蛇形路径是空字符串。我们从检查中知道LCS是一个空字符串,但是我们想展示算法来证明它。

首先我们需要找到中蛇。如果您按照算法查找第11页的中间蛇,您将看到最短编辑脚本的长度为2,(x,y)=(u,v)=(1,0)或(0,1) )。换句话说,它是路径中间的一条空蛇。

算法伪代码有一些非显而易见的符号约定:

  1. 如果n
  2. 在对LCS的递归调用中,第一个呼叫使用ceiling(D / 2)作为D,第二个呼叫使用floor(D / 2)。这在第12页的算法上方的文本中更清楚。
  3. 因此,在这个例子中,假设第一次调用LCS找到一条中间蛇,其中(x,y)=(u,v)=(1,0),那么由于D = 2,结果就是扩展的:

    LCS(A[1..1], 1, B[1..0], 0)  // Output nothing since M = 0
    Output A[2..1]               // Output nothing since it is an empty string.
    LCS(A[2..1], 0, B[1..1], 1)  // Output nothing since N = 0
    

    这是正确的,因为这些字符串没有共同的子序列。