Skip to content

KMP 算法

介绍

KMP 算法是一种改进的字符串匹配算法。

KMP 算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。

具体实现就是通过一个 next() 函数实现,函数本身包含了模式串的局部匹配信息。

KMP 算法的时间复杂度 O(m+n)

详解

详见代码:Code

核心代码:

void pre()//求 P 数组(即 next 数组) 
{
    P[1]=0;//记得本题中字符串从 1 开始 
    int j=0;
    for(int i=1;i<m;i++)
    {
        while(j>0 && B[j+1]!=B[i+1])
            j=P[j];
        if(B[j+1]==B[i+1])
            j++;
        P[i+1]=j;
    }
}

一、KMP 算法

目的:找到模式串 B 在原字符串 A 中 第一次出现的位置。

nm 分别为 AB 的长度

流程:

[STEP 1]
if A[i+1]==B[j+1]
    i++,j++;

   i
A: ababcabcacbab
B: abcac
   j
[STEP 2]
if A[i+1]==B[j+1]
    i++,j++;

    i
A: ababcabcacbab
B: abcac
    j
[STEP 3]
if A[i+1]!=B[j+1]
    j=next[j];

    i
A: ababcabcacbab
B:   abcac
    j

if A[i+1]==B[j+1](如果不等于的话就只加i)
    i++,j++;

     i
A: ababcabcacbab
B:   abcac
     j
[STEP 4]
略

二、next 数组的求法

next 数组记录最长相同前缀后缀

具体来说,就是 next 数组负责记录 B 字符串(也就是待查找子串)每个位置的属性,next[i] 记录 B[0…i] 中的前缀和后缀最长有多少一样的,比如 abcdab 中,[ab]cde[ab] 最长相同前缀后缀为 ab

例:

a   next[0]=0(注意!这是默认值 0 ,不是 1 )
ab  next[1]=0(a!=b)
abc next[2]=0(a!=c)
abca    next[3]=1(a==a)
abcab   next[4]=2(ab==ab)
abcabc  next[5]=3(abc==abc)

next 数组的操作与 KMP 类似

例:abcaba

初始状态
   0
   i
B: abcaba
  j
if B[j+1]!=B[i+1]
    i++;

   00
    i
B: abcaba
  j
if B[j+1]!=B[i+1]
    i++;

   000
     i
B: abcaba
  j
if B[j+1]==B[i+1]
    i++,j++;

   0001
      i
B: abcaba
   j
if B[j+1]==B[i+1]
    i++,j++;

   00012
       i
B: abcaba
    j
if B[j+1]!=B[i+1]
    j=next[j];

if B[j+1]==B[i+1]
    i++,j++;

   000121
        i
B: abcaba
   j

注:部分资料来源于百度百科


Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.