KMP算法深入浅出

来源:互联网 发布:旧版淘宝下载2015 编辑:程序博客网 时间:2024/05/17 08:58


    S:  ababcababa

    P:  ababa


KMP算法与BF算法的区别就在于KMP算法巧妙的消除了指针i的回溯问题,只需确定下次匹配j的位置即可,使得问题的复杂度由O(mn)下降到O(m+n)。

在KMP算法中,为了确定在匹配不成功时,下次匹配时j的位置,引入了next[]数组,next[j]的值表示P[0...j-1]中最长后缀的长度等于相同字符序列的前缀。

  对于next[]数组的定义如下:

 1) next[j] = -1  j = 0

 2) next[j] = max(k): 0<k<j   P[0...k-1]=P[j-k,j-1]

 3) next[j] = 0  其他

 如:

 P      a    b   a    b   a

 j      0    1   2    3   4

 next    -1   0   0    1   2

其实如果这段你觉得很难看懂(确实开始挺难看懂的),那么我们就实际的比量一下

next[0]=-1,next[1]=0,这个就是约定俗成了,不管它了。其余的j,就是相当于p[0,j-1]这个串里,重合度最高的那两个字串,它们的长度,这两个字串要满足什么条件呢?第一个子串的开始位置是0,第二个子串的结尾位置是j-1,上例中next[4]为什么等于2?因为p[0,4]=abab,而abab重合度最高的就是ab,它恰好也满足上述条件,于是next[4]=2.

再例:

 T      a    b   a    a   b  d

 j      0    1   2    3   4   5

 next    -1   0   0    1   1   2

这回比较明白了吧?当然这个next的表示,有人是以-1作为基数的,有人为0作基数,都不打紧,你要是愿意以0作基数,那每个next元素上都+1就完了呗,为了接近计算机表示法,我还是支持以-1作为基数

next算出来了,然后怎么用呢?

在匹配过程中,先从若发生不匹配的情况,如果next[j]>=0,则目标串的指针i不变,将模式串的指针j移动到next[j]的位置继续进行匹配;若next[j]=-1,则将i右移1位,并将j置0,继续进行比较。

这回可以很快地从S中找到P了吧?