KMP模板与详解

原理浅析

zyf:

求失配的过程和最后比较的过程差不多,因为每次都是如果不匹配就跳到它失配的位置。
至于为什么是这样,可以想象一下失配也就是说头和尾上的一段字符串是一模一样的,那么我们在头上不停地往前跳,也就相当于在结尾不停地往后跳(自己体会一下)。

KMP一开始看有点晕,你先要知道的是,它是先自己和自己弄,再和大串弄
i是a串(大串)的指针,j是b串(小串)的指针

E.G.

a b a b a b a b e
a b a b e

啊,你发现这里炸了,因为b[1]=b[3],b[2]=b[4]你完全可以,直接这样:

a b a b a b a b e
。。。。 a b a b e

而不是这样:

a b a b a b a b e
. a b a b e

代码

原理就是这样,代码实现上
预处理出这样一个数组p[j],表示当匹配到b数组的第j个字母而第j+1个字母不能匹配了时,新的j最大是多少。
这样可以使得A[i-j+1..i]与B[1..j]保持匹配(此处为新的j)。
然后,下一位如果还是不能匹配,再把前一个j翻出来,再匹配一次,直到找不到相同的前缀了也就是j=0了,就只能把整个串往后挪一位了

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1000001;

char a[maxn],b[maxn];
int la,lb,p[maxn];

int main()
{
    scanf("%s%s",a+1,b+1);
    la=strlen(a+1); lb=strlen(b+1);
    int j=0;//首先b和b自身匹配 
    p[1]=0;
    for (int i=2; i<=lb; i++)//从2开始? 
    {
        while (j>0 && b[i]!=b[j+1]) j=p[j];
        if (b[i]==b[j+1]) j++;
        p[i]=j;//更新p 
    }
    j=0;
    for (int i=1; i<=la; i++)
    {
        while (j>0 && a[i]!=b[j+1]) j=p[j];
        if (a[i]==b[j+1]) j++;
        if (j==lb)
        {
            printf("%d\n",i-lb+1);//输出子串的位置
            j=p[j];
        }
    }
    for (int i=1; i<=lb; i++) printf("%d ",p[i]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值