我找到了Longest Common Substring的算法。通常使用dynamic programming
使用大小为mxn
的二维数组来完成,其中m
和n
是所考虑的两个字符串的长度。
我将为两个字符串构建以下矩阵。
M[i][j] = 1 if s1[i]==s2[j] else 0.
例如,如果字符串为:abcxy
和pqaabx
矩阵如下所示:
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)
。所以,不需要记忆。
有人能指出我哪里出错吗?
答案 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)。如果使用位矩阵表示,您的解决方案可以节省一些内存,而另一种解决方案可能稍快一些。