KMP学习

来源:互联网 发布:gentoo linux pdf 编辑:程序博客网 时间:2024/05/22 11:39

推荐一篇的博客:http://www.matrix67.com/blog/archives/115

学习了一下KMP,主要用来字符串匹配,比较重要的一个数组就是失配数组。这里用数组P来表示。

p[i]=k表示p[1~k]和p[i-k+1~i]相同,举个简单的例子p[i]=2,就是表示p[1~2]和p[i-1~i]相同。

如果构造出了p数组。那么在查询的时候(设文章为A,单词为B),A[i]≠B[j],则j要往回跳,即j=p[j],接下来判断B[j+1]是否与A[i]相同,如果不同,则继续跳,除非相同或跳到了开头(j=0)。


最后一个问题就是如果构造出P数组,事实上是线性的,举一个例子。

单词为ababacb。

我们把p[1]初始化为0,假设我们求出了p[2]=0,p[3]=1,p[4]=2,在求P[5]的时候,判断B[5]是否等于B[p[4]+1],发现成立。所以p[5]=p[4]+1=3。求p[6],判断B[6]是否等于B[p[5]+1],发现不成立,这个时候j又要往回跳(理解一下),结束条件和上面的相同。


模板代码:

#include<cstdio>
#include<cstring>
using namespace std;

#define rep(i,a,b) for (int i=a;i<=b;++i)

int p[105];
char a[105],b[105];
int j,la,lb,i;

int main()
{
    scanf("%s",a+1);
    scanf("%s",b+1);
    la=strlen(a+1);
    lb=strlen(b+1);
    p[1]=j=0;
    rep(i,2,lb)
    {
        for (;j&&(b[j+1]^b[i]);j=p[j]);
        if (b[j+1]==b[i]) ++j;
        p[i]=j;
    }
    j=0;
    rep(i,1,la)
    {
        for (;j&&(b[j+1]^a[i]);j=p[j]);
        if (b[j+1]==a[i]) j++;
        if (j==lb) printf("%d",i-lb+1);
    }
    return 0;
}