KMP

学习KMP强烈推荐:严蔚敏老师的教学视频:http://www.56.com/u59/v_NjAwMzA0ODA.html

时长一小时,但绝对受益匪浅。


简单地总结一下我现在所掌握的KMP吧:

首先,需要明确的是KMP是处理什么问题的:求一个串(为了好理解下面的代码,姑且认为这个串为T)在另一个串(S)中完全匹配后的id,也就是说S中子串T的起始位置。

面对这个问题,我们很容易想到暴力的方法,就是两个for,一个一个去比,但是当出现:S:aa…aaas,T:aas时,复杂度就是O(m*n)(m:S的串长,n:T的串长),这样的复杂度做题时受不了的。于是,有个k啥,m啥,p啥的三个人研究出了一种算法,这种算法最坏的情况下是线性的,即复杂度是O(m+n);

了解kmp算法,首先需要了解kmp算法的核心和精华那就是next[]数组。(这个next数组的理解将至关重要,因为题目不可能是上述的那么简单,一般需要你在预处理next数组上做手脚)

首先我们不管next数组是什么,我们先来看一下next数组的作用:

假设我们已经在S中找到一段(从第i位开始)与T前半部分匹配的串,即 S的第i+j位与T的第j位不匹配,那么接下来我们如果按照暴力的方法,就是要比较S[i+1...i+j+1]与T[0...n],我们现在关注的是上述比较的前半部分,即:S[i+1...i+j+1]与T[0...j],有必要一个一个再比较一次么?没有。因为在已知的比较中我们知道S[i+1...i+j]与T[1...j]是相等的,所以就只是比较T[1...j]与T[0...j-1]了,如果我们预处理好一个数组,表示从第j位开始,前面next[j]位与T串的开头匹配,那么就很好判断了。如果第i位与next[j]相等,那么i++,j++,否则j=next[j]。直到两个串中的任意一个跑完。

这就是next数组的作用,和kmp算法的思路。

下面是自己的代码:

#include<cstdio>
#include<cstring>
const int mmax=100005;
char ss[mmax],tt[mmax];
int next[mmax];
void getnext()
{
    int len=strlen(tt);
    next[0]=-1;
    for(int i=0,j=-1;i<len;)
    {
        if(j==-1 || tt[i]==tt[j])
        {
            i++,j++;
            if(tt[i]!=tt[j])
                next[i]=j;
            else
                next[i]=tt[j];
        }
        else
            j=next[j];
    }
}
int kmp()
{
    int i,j;
    int lens=strlen(ss);
    int lent=strlen(tt);
    for(i=0,j=0;i<lens && j<lent;)
    {
        if(j==-1 || ss[i]==tt[j])
            i++,j++;
        else
            j=next[j];
    }
    if(j==lent)
        return i-lent;
    return -1;
}
int main()
{
    while(scanf("%s %s",ss,tt)!=EOF)
    {
        getnext();
        int ans=kmp();
        printf("%d\n",ans);
    }
    return 0;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值