KMP算法用于串的模式匹配,主串S,子串T(也叫模式串),模式匹配意思是从S中找出跟T一样的子串,就是说判断S是否包含T,时间复杂度O(m+n),实现这个算法关键有两步,第一步,求next数组,第二步KMP主算法

如何理解next数组,**next[j]表示当子串T中第j个字符与主串中相应字符“失配”时,在子串T中需要重新和主串S中该字符进行比较的字符的位置。**例子:
求:主串S=“ababcabcacbab”,子串T=“abcac”KMP算法匹配过程
假如说已经求出来next数组(最后再研究next数组怎么求)如下:
跳出课本学KMP算法
下面进行KMP匹配,i与j分别标记主串与子串位置,且都从1开始
跳出课本学KMP算法
如上图,我们从主串S第1位a开始对应匹配,匹配时候发现i等于3,j等于3时候不匹配,怎么办呢?一般我们都会从主串S第2位b开始再和abcac逐个匹配,但有了next数组就不必那样做了,此时i不必退到第2位b处,应保持不动,主串不动,子串那必须行动行动,因为不匹配位置j=3,根据next数组说法,next[j]表示当子串T中第j个字符与主串中相应字符“失配”时,在子串T中需要重新和主串S中该字符进行比较的字符的位置,此时next[3]=1,故j移动到T的第1位,即用T第1位与Si所指的第3位继续匹配比较,如下:
跳出课本学KMP算法
可以看出,再次匹配时,i=7,j=5时候有不匹配了,此时再处理处理,保持i=7不动,j变为:j=next[j],此时j等于2,如下:
跳出课本学KMP算法
接下来按照以上步骤一步步来(能看出来此时其实已经匹配好了)

所以KMP匹配代码就容易写了(纯C):

int KMP(char  S[], char  T[], int pos)
{
    i=pos; j=1;//post表示从主串什么位置开始,一般情况下都是从1开始的
    while(i<=strlen(S)-1&&j<=strlen(S)-1)//strlen(S)-1是实际长度,S[0]不是真正字符内容
    {
        if (j==0||S[i]==T[j])//匹配到了的话继续往前走直到遇到不匹配的或匹配成功了
        {
            i++;
            j++;
        }
        else
        {
            j=next[j];//当子串T中第j个字符与主串中相应字符“失配”时,在子串T中需要重新和主串S中该字符进行比较的字符的位置
        }
    }
    if (j>=strlen(S))
        return i-T[0];//匹配位置
    else
        return 0;
}

还有一个遗留问题:如何求next
跳出课本学KMP算法
观察此表,发现
next[j]表示前j-1个字符前后缀失配位置
即next[j]表示前j-1个字符前后缀匹配数目+1,基于此:

void get_next(char T, char  next[ ]{
    i=1; next[1]=0; j=0;
    while(i<T[0])
    {
        if (j==0||T[i]==T[j])
            i++;
        j++;
        next[i]=j;
        else
            j=next[j];
    }
}

相关文章:

  • 2022-01-22
  • 2022-12-23
  • 2022-02-24
  • 2021-07-26
  • 2021-11-21
  • 2021-12-02
  • 2022-01-16
猜你喜欢
  • 2021-08-13
  • 2021-08-06
  • 2022-12-23
  • 2022-12-23
  • 2021-10-10
相关资源
相似解决方案