KMP算法中如何求next数组

使用KMP算法寻找子串的第一次出现位置

KMP算法思想:当匹配失效时,若在失效的之前存在一个最大重复子串,则可以从重复子串的下一个字符开始比较,不必要回溯到开始0的位置;故核心是找到失效位置对应的回退位置,即最大重复子串。这个重复子串的头是0,其长度为k,存放在next[j]中

KMP的关键是求next数组:next[j]是指回退后的比较位置,是最大重复串的下一个字符。字符串下标从0开始,故当最大重复串长度为k时,next[j]=k,k是下标,对应了第k+1个字符。

当p[j]匹配时求j+1匹配失效时,回退到哪里的问题,分两种p[k]==p[j] /p[k]!=p[j]

  • 当p[k]==p[j]时,因p[0~k-1]==p[j-k~j-1]且p[k]==p[j],故p[0~k]=p[j-k ~ j],说明最大重复串长度增加1,故next[j+1]=k+1=next[j]+1

  • 当p[k] != p[j] 时,若p[j+1]与s[i]匹配失效,因p[j]==s[i-1]且p[k]!=p[j],则p[k]也不等于s[i-1],p[0~k] 和主串必然不匹配,需要回退。这等效于p[k]与s[i-1]不匹配,故j+1最大重复子串长 k=next[k]

代码如下

int gen_next(int *next,char substr[], int len)
{
    int i=0;
    int k=-1,j=0;
    next[0] = -1;
    while(j

优化:

当p[++j] 与p[++k]相等时,若p[j+1]与s[i]匹配失败回退到p[k]时,p[k]必然与s[i]不匹配,需要再次回退到p[next[k]],故这里可以直接让next[j]=next[k],即跳过p[k]与s[i]这次无效的比较

代码如下

int gen_next_improve(int *next,char substr[], int len)
{
    int i=0;
    int k=-1,j=0;
    next[0]=-1;
    while(j

你可能感兴趣的:(C/C++,算法,数据结构)