这种最长公共子串的方法是否正确?

时间:2014-02-27 13:40:14

标签: algorithm longest-substring

我找到了Longest Common Substring的算法。通常使用dynamic programming使用大小为mxn的二维数组来完成,其中mn是所考虑的两个字符串的长度。

我将为两个字符串构建以下矩阵。

M[i][j] = 1 if s1[i]==s2[j] else 0.

例如,如果字符串为:abcxypqaabx

矩阵如下所示:

    a b c x y
 p  0 0 0 0 0
 q  0 0 0 0 0
 a  1 0 0 0 0
 a  1 0 0 0 0
 b  0 1 0 0 0
 x  0 0 0 1 0

现在,我在左上角到右下角的每个对角线上搜索1 s的最大连续序列。

这些中的最大值将是答案。

我可以在不使用数组的情况下执行上述操作。时间复杂度仍为O(M*N)。所以,不需要记忆。

有人能指出我哪里出错吗?

2 个答案:

答案 0 :(得分:1)

你的方法是正确的。为了证明,假设S1和S2的最长公共子串来自S1 [i..j]和S2 [p..q]。 这意味着 S1 [i + k] = S2 [p + k]

这些都位于从(i,p)开始的对角线上。

动态编程解决方案做同样的事情,但不是先计算表格并通过对角线路径,而是根据它的对角线父级加上它们是否匹配来计算表格。

<强> EDITED

关于使用额外内存对维基百科解决方案的评论。它只是为了清晰起见。原则上,维基百科解决方案中只需要两行矩阵,并将当前最大计数保留在一个变量中。这是正确的,因为对于矩阵中的任何(i,j)条目

M(i,j)= 1 + M(i-1,j-1)(如果s1 [i] == s2 [j])

正如您所看到的,当前行元素仅取决于紧邻上行的元素。

答案 1 :(得分:1)

您的算法是正确的,但标准DP方法会消除您的第二阶段,并使解决方案更简单。

您可以在构建矩阵时计算对角线长度,而不是标记布尔值,然后扫描对角线以查找最长的序列 - 只需要一次传递。

就时间和空间复杂性而言,两种解决方案都是O(NxM)。如果使用位矩阵表示,您的解决方案可以节省一些内存,而另一种解决方案可能稍快一些。