确定长度为N的数组是否在长度为M的数组中

时间:2013-02-02 20:58:27

标签: java algorithm

  

可能重复:
  Algorithm to determine if array contains n…n+m?

让我们假设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寻找匹配。

我猜这个问题在采访中相当普遍,所以我的问题是询问是否有更快的方法。

1 个答案:

答案 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中。