让我们假设M> N,你有2个阵列。其中一个长度为M,一个长度为N,称为B.是否有更快的方法来确定阵列B中是否存在阵列B?
例如:
A = [1 2 3 4 5 6]
B1 = [2 3 4]
所以阵列B1存在于A中,而[1 3 2]则不存在。
这实际上是在Java中使用char数组实现类似isSubstring()的东西。
我能想到的唯一方法是在O(n ^ 2)中,你将A中的每个元素与B中的初始元素进行比较,并迭代通过B寻找匹配。
我猜这个问题在采访中相当普遍,所以我的问题是询问是否有更快的方法。
答案 0 :(得分:2)
您需要KMP
算法kmp_search: 输入: 一个字符数组,S(要搜索的文本) 一个字符数组,W(寻求的单词) 输出: 一个整数(在S中找到W的从零开始的位置)
define variables: an integer, m ← 0 (the beginning of the current match in S) an integer, i ← 0 (the position of the current character in W) an array of integers, T (the table, computed elsewhere) while m+i is less than the length of S, do: if W[i] = S[m + i], if i equals the (length of W)-1, return m let i ← i + 1 otherwise, let m ← m + i - T[i], if T[i] is greater than -1, let i ← T[i] else let i ← 0 (if we reach here, we have searched all of S unsuccessfully) return the length of S
复杂性:
假设表T的先前存在,则搜索部分 Knuth-Morris-Pratt算法具有复杂度O(k),其中k是 S的长度和O是大O符号。除了固定的 所有的进入和退出功能所产生的开销 计算是在while循环中执行的,我们将计算一个 限制此循环的迭代次数;为了做到这一点,我们 首先对T的性质做一个关键的观察。通过定义它 构造成如果在S [m]处开始的匹配失败的话 比较S [m + i]和W [i],那么下一个可能的匹配必须从 S [m +(i - T [i])]。特别是下一个可能的匹配必须发生在 指数高于m,因此T [i] <一世。使用这个事实,我们将展示 循环最多可以执行2k次。对于每次迭代,它 执行循环中的两个分支之一。第一个分支 总是增加i并且不改变m,所以指数m + i 目前审查的S字符的数量增加了。第二 分支将i - T [i]添加到m,正如我们所看到的,这总是一个 正数。因此,电流开始的位置m 潜在的匹配增加了。现在,如果m + i = k,则循环结束; 因此,循环的每个分支最多可达到k次, 因为它们分别增加m + i或m,并且m≤m+ i:if m = k,那么当然m +i≥k,因此它以单位增加 最多增量,我们必须在某个点上有m + i = k 过去,因此我们将采取任何一种方式。因此循环 执行最多2k次,显示时间复杂度 搜索算法是O(k)。
其他信息:
KMP算法的效率
由于算法的两个部分分别具有 O(k)和O(n)的复杂性,整体算法的复杂性 是O(n + k)。无论有多少,这些复杂性都是一样的 重复模式在W或S中。