【问题标题】:Can i check if subsequence faster then O(n*n)我可以检查子序列是否比 O(n*n) 快吗
【发布时间】:2014-05-03 11:25:41
【问题描述】:

所以我的问题在于主题名称。是否存在比 O(N^2) 更快地检查 B 是否是 A 的子序列的算法,例如 O(NlogN) 或简单的 O(N)?

找到的唯一方法是简单的蛮力

for(int i = 0; i < a.Length - b.Length; i++)
{
   if (IsSubsequence(a,b,i))
      return i;
}
return -1;

【问题讨论】:

  • 您应该定义子序列并举一个例子以避免混淆。也请为IsSubsequence 添加您的代码
  • 因为通常子序列的含义与您所要求的不同

标签: c# .net performance algorithm complexity-theory


【解决方案1】:

是的,使用Knuth, Morris and Pratt 的算法可以比O(n^2) 更快地完成。但是请注意,framework 提供的实现可能已经实现了这个算法。

【讨论】:

  • 子序列,不是子字符串
  • 我已经将答案更改为链接到Contains 方法而不是Substring 方法。您的“子序列”是指完全不同的东西吗?
  • @Codor:子串是一种特殊的子序列。如果您有序列“A,B,C,D,E”,那么“A,C,E”是子序列,但不是子字符串。 "B, C, D" 既是子序列又是子串。子字符串没有“间隙”。 KMP 查找子字符串,而不是子序列。
  • 谢谢你的评论,我误解了这个问题。
【解决方案2】:

是的,下面的贪心算法是正确的,运行时间为 O(n)。对于 B 中的每个元素,从上一个停止点(最初是 A 的开头)向前扫描 A 中的第一个元素。

【讨论】:

  • 当我们有两个嵌套循环时,你是如何得到 O(n) 的?
  • @AlexJoukovsky 它们是嵌套的,因为这就是实现它们的方式,但是内部循环最多只能对 A 进行一次扫描。您可以将它们视为非嵌套的,具有控制权流来回ping。
【解决方案3】:

这是 David Eisenstat 算法的递归特征。 (注意,这个算法是尾递归,因此可以写成一个循环;我把它描述为递归,因为这样做是理解算法的好方法。)

将一个序列定义为空的,或者一个项目后跟一个序列。

取两个序列,A 和 B。问题是 B 是否是 A 的子序列。

如果 B 为空,则 B 是 A 的子序列。

如果 B 不为空且 A 为空,则 B 不是 A 的子序列。

如果我们走到这一步,A 和 B 都不是空的。假设 A 是项目 X 后跟序列 C,B 是项目 Y 后跟序列 D。

如果 X 与 Y 相同,那么问题的答案是“B 是 A 的子序列吗?”与小问题“D 是 C 的子序列吗?”的答案相同。回答这个问题。

如果 X 与 Y 不同,那么问题的答案是“B 是 A 的子序列吗?”与小问题“B 是 C 的子序列吗?”的答案相同。回答这个问题。

这个过程终止了,显然它最坏的情况是在序列 A 的长度中。

【讨论】:

    猜你喜欢
    • 2020-01-15
    • 1970-01-01
    • 1970-01-01
    • 2021-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多