KMP算法中如何求next数组

KMP算法是一种用于字符串匹配的高效算法,主要思想是在匹配失效时利用已知的最大重复子串来避免回溯。关键在于构造next数组,它表示在匹配过程中遇到不匹配时的回退位置。当匹配成功时,next[j+1]=next[j]+1;否则,如果p[k]与p[j]不等,则next[j]=next[k],跳过无效比较。优化后的代码更高效地计算next数组。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用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<len-1){
        if(k ==-1 || next[k] == next[j]){
            next[++j]=++k;
        } else {
            k=next[k];
        }
    }
}

优化:

当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<len-1){
        if(k==-1 || next[k] == next[j]){
            if(next[++j] == next[++k])
                next[j]=next[k];
            else
                next[j]=k;
        } else {
            k=next[k];
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值