KMP 模板


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#define N 100
using  namespace std;
int next[N];
char s[N],t[N];
int slen,tlen;

void getNext()
{
    int j,k;
    j=0;k=-1;next[0]=-1;
    while(j<tlen)
    {
        if(k==-1||t[j]==t[k])next[++j]=++k;
        else k=next[k];
    }
}

//返回模式串t在主串s中首次出现的位置
int kmp_Index()
{
    int i=0,j=0;
    getNext();
    while(i<slen&&j<tlen)
    {
        if(j==-1||s[i]==t[j])
        {
            i++;
            j++;
        }
        else j=next[j];
    }
    if(j==tlen)return i-tlen;
    else return -1;
}

//返回模式串t在主串s中出现的次数
int kmp_Count()
{
    int ans=0;
    int i,j=0;
    if(slen==1&&tlen==1)
    {
        if(s[0]==t[0])return 1;
        else return 0;
    }
    getNext();
    for(i=0;i<slen;i++)
    {
        printf("***%d %d\n",i,j);
        while(j>0&&s[i]!=t[j])j=next[j];
        if(s[i]==t[j])j++;
        if(j==tlen)
        {
            ans++;
            j=next[j];
        }

    }
    return ans;
}

int main()
{
    while(cin>>s>>t)
    {
        slen=strlen(s);
        tlen=strlen(t);
        printf("%d %d\n",kmp_Index(),kmp_Count());
        for(int i=0;i<=tlen;i++)printf("%d %d\n",i,next[i]);
    }
    return 0;
}
/*
in:
abbaabbaaba  abbaaba

out:

4 1
0 -1
1 0
2 0
3 0
4 1
5 1
6 2
7 1


*/

poj3461模式匹配

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#define N 1000000
using  namespace std;
int next[N];
char s[N],t[N];
int slen,tlen;

void getNext()
{
    int j,k;
    j=0;k=-1;next[0]=-1;
    while(j<tlen)
    {
        if(k==-1||t[j]==t[k])next[++j]=++k;
        else k=next[k];
    }
}

//返回模式串t在主串s中出现的次数
int kmp_Count()
{
    int ans=0;
    int i,j=0;
    if(slen==1&&tlen==1)
    {
        if(s[0]==t[0])return 1;
        else return 0;
    }
    getNext();
    for(i=0;i<slen;i++)
    {
     //   printf("***%d %d\n",i,j);
        while(j>0&&s[i]!=t[j])j=next[j];
        if(s[i]==t[j])j++;
        if(j==tlen)
        {
            ans++;
            j=next[j];
        }

    }
    return ans;
}

int main()
{
    int tt;
    cin>>tt;
    while(tt--)
    {
        cin>>t>>s;
        slen=strlen(s);
        tlen=strlen(t);
        printf("%d\n",kmp_Count());
       // for(int i=0;i<=tlen;i++)printf("%d %d\n",i,next[i]);
    }
    return 0;
}

poj2406 利用next数组即可,len-next【len】表示最短循环长度,如果len%(len-next【len】)==0 最大循环数为len/(len-next【len】)否则为1

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#define N 1000000
using  namespace std;
int next[N];
char t[N];
int tlen;

void getNext()
{
    int j,k;
    j=0;k=-1;next[0]=-1;
    while(j<tlen)
    {
        if(k==-1||t[j]==t[k])next[++j]=++k;
        else k=next[k];
    }
}

int main()
{
    while(cin>>t)
    {
        if(t[0]=='.')break;
        tlen=strlen(t);
        getNext();
        if(tlen%(tlen-next[tlen])==0)printf("%d\n",tlen/(tlen-next[tlen]));
        else printf("1\n");
    }
    return 0;
}

POJ1961 和上题差不多,加一个for循环

题目大意:

给你一个字符串,求这个字符串到第i个字符为止的循环节的次数。

比如aabaabaabaab,长度为12.到第二个a时,a出现2次,输出2.到第二个b时,aab出现了2次,输出2.到第三个b时,aab出现3次,输出3.到第四个b时,aab出现4次,输出4.

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#define N 1000000
using  namespace std;
int next[N];
char t[N];
int tlen;

void getNext()
{
    int j,k;
    j=0;
    k=-1;
    next[0]=-1;
    while(j<tlen)
    {
        if(k==-1||t[j]==t[k])next[++j]=++k;
        else k=next[k];
    }
}

int main()
{
    int k=1;
    while(cin>>tlen)
    {
        if(tlen==0)break;
        cin>>t;
        getNext();
        int i;
        // for(i=0;i<=tlen;i++)printf("%d %d\n",i,next[i]);
        if(k>1)printf("\n");
        printf("Test case #%d\n",k++);
        for(i=2; i<=tlen; i++)
        {
            if(i%(i-next[i])==0&&i/(i-next[i])>1)printf("%d %d\n",i,i/(i-next[i]));
        }
    }
    return 0;
}


POJ2752 先放着 有空写一下、、



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值