【问题标题】:Is this method of Longest common substring correct?这种最长公共子串的方法是否正确?
【发布时间】:2014-02-27 13:40:13
【问题描述】:

我找到了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

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

其中的最大值就是答案。

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

谁能指出我哪里出错了?

【问题讨论】:

  • 我觉得不错 - 你有什么理由认为这不正确吗?
  • @PeterdeRivaz 如果这是正确的,那么为什么wikipedia 使用使用额外内存的算法?我也没有找到任何具有O(MN) 复杂性且没有额外内存的解决方案。

标签: algorithm longest-substring


【解决方案1】:

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

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

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

已编辑

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

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

如您所见,当前行元素仅依赖于上一行的元素。

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 我其实不想使用矩阵。我强调同样的操作也可以在没有矩阵的情况下完成。我的意思是只使用两个loops
    • @nitish712:实际上你是对的,你可以只使用恒定的额外空间和 O(NxM) 时间来做到这一点。但请注意,Wikipedia 页面并未建议使用何种数据结构 - 它仅使用表格描述递归过程。
    猜你喜欢
    • 2013-04-13
    • 1970-01-01
    • 1970-01-01
    • 2014-04-14
    • 1970-01-01
    • 2016-06-03
    • 2010-11-28
    • 2014-03-31
    • 1970-01-01
    相关资源
    最近更新 更多