POJ KMP各类题型

如果要学习KMP的话,我推荐2篇博客,我觉得非常棒

1:http://blog.csdn.net/v_july_v/article/details/7041827

2:http://www.matrix67.com/blog/archives/115

下面是一些KMP类题(不定期更新):

POJ3461

题目链接:http://poj.org/problem?id=3461

  这题就是KMP算法裸题,直接代码:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int next[10005];
char p[10005],s[1000005];
void getnext(char *t,int *next)
{
    int len=strlen(t);
    int i=0,j=-1;
    next[0]=-1;
    while(i<len)
    {
        if(j==-1||t[i]==t[j])
        {
            if(t[i]==t[j]) j=next[j];
            else
                next[++i]=++j;
        }
        else
            j=next[j];
    }
}
int kmp(char *a,char *b)
{
    int i=0,j=0,ans=0;
    int alen=strlen(a);
    int blen=strlen(b);
    while(i<alen)
    {
        if(j==-1||a[i]==b[j])
        {
            ++i;
            ++j;
        }
        else
            j=next[j];
        if(j==blen) ans++;
    }
    return ans;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s%s",p,s);
        getnext(p,next);
        printf("%d\n",kmp(s,p));
    }
    return 0;
}

POJ 2406(求最小循环节的个数)

     KMP的next表示模式串如果第i位(设str[0]为第0位)与文本串第j位不匹配则要回到第next[i]位继续与文本串第j位匹配。则模式串第1位到next[n]与模式串第n-next[n]位到n位是匹配的。所以思路和上面一样,如果n%(n-next[n])==0,则存在重复连续子串,长度为n-next[n]。

例如:a    b    a    b    a    b

next: -1    0    0    1    2    3    4

next[n]==4,代表着,前缀abab与后缀abab相等的最长长度,这说明,ab这两个字母为一个循环节,长度=n-next[n];

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int next[1000005];
char a[1000005];
void getnext(char *p,int len)
{
    int j=0,k=-1;
    next[0]=-1;
    while(j<len)
    {
        if(k==-1||p[j]==p[k])
        {

            next[++j]=++k;
        }
        else
            k=next[k];
    }
}
int main()
{
    while(scanf("%s",a)!=EOF)
    {
        if(a[0]=='.') break;
        int len=strlen(a);
        getnext(a,len);
        if(len%(len-next[len])==0)
            printf("%d\n",len/(len-next[len]));
        else
            printf("1\n");
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值