KMP

POJ 3461

Sample Input
3
BAPC
BAPC
AZA
AZAZAZA
VERDI
AVERDXIVYERDIAN

Sample Output
1
3
0
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#define ll long long
#define mem(a,x) memset((a),(x),sizeof ((a)))//x只能是0或-1
#define debug(x) cout<<"X: "<<(x)<<endl
#define de cout<<"************"<<endl
#define lowbit(x) ((x)&(-x))
#define lson rt<<1
#define rson rt<<1|1
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/(__gcd(a,b))
#define inf 0x3f3f3f3f//1e9+6e7
#define eps 1e-8
#define mod 1e9+7
#define N 1000010
const double pi=acos(-1.0);
using namespace std;
char S[N];  //主串
char T[N];  //模式串
int slen,tlen,ans;
int Next[N];
void getNext()
{
    int i=0,j=-1;
    Next[0]=-1;
    while(i<tlen)
    {
        if(j==-1||T[i]==T[j])
            Next[++i]=++j;
        else
            j=Next[j];
    }
}
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;
}
int KMP_Count()
{
    int ret=0,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++)
    {
        while(j>0&&S[i]!=T[j])
            j=Next[j];
        if(S[i]==T[j])
            j++;
        if(j==tlen)
        {
            ret++;
            //j=i+1;  //如果求主串中包含几个模式串 j=i+1
            j=Next[j];//如果求模式串在主串中出现的次数 j=Next[j]
        }
    }
    return ret;
}

int main()
{
    int TT;
    cin>>TT;
    while(TT--)
    {
        memset(S,0,sizeof S);//主串
        memset(T,0,sizeof T);//模式串
        cin>>T>>S;
        tlen=strlen(T);
        slen=strlen(S);
        //复杂度:O(n+m)
        //cout<<KMP_Index()<<endl;    //模式串T在主串S中首次出现的位置,如果不存在,则输出-1
        cout<<KMP_Count()<<endl;    //模式串T在主串S中出现的次数或主串中包含几个模式串
    }
    return 0;
}

HDU 1771

Sample Input
2
13 5
1 2 1 2 3 1 2 3 1 3 2 1 2
1 2 3 1 3
13 5
1 2 1 2 3 1 2 3 1 3 2 1 2
1 2 3 2 1

Sample Output
6
-1
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#define ll long long
#define mem(a,x) memset((a),(x),sizeof ((a)))//x只能是0或-1
#define debug(x) cout<<"X: "<<(x)<<endl
#define de cout<<"************"<<endl
#define lowbit(x) ((x)&(-x))
#define lson rt<<1
#define rson rt<<1|1
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/(__gcd(a,b))
#define inf 0x3f3f3f3f//1e9+6e7
#define eps 1e-8
#define mod 1e9+7
#define N 1000010
const double pi=acos(-1.0);
using namespace std;
int S[N];  //主串
int T[N];  //模式串
int slen,tlen,ans;
int nxt[N];
void getNext()
{
    int i,j;
    i=0;j=-1;nxt[0]=-1;
    while(i<tlen)
    {
        if(j==-1||T[i]==T[j])
            nxt[++i]=++j;
        else
            j=nxt[j];
    }
}
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=nxt[j];
    }
    if(j==tlen)
        return i-tlen;
    else
        return -1;
}
int KMP_Count()
{
    int ret=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++)
    {
        while(j>0&&S[i]!=T[j])
            j=nxt[j];
        if(S[i]==T[j])
            j++;
        if(j==tlen)
        {
            ret++;
            //复杂度:O(n+m)
            //j=i+1;  //如果求主串中包含几个模式串 j=i+1
            j=nxt[j];//如果求模式串在主串中出现的次数 j=nxt[j]
        }
    }
    return ret;
}

int main()
{
    int TT;
    cin>>TT;
    while(TT--)
    {
        memset(S,0,sizeof S);//主串
        memset(T,0,sizeof T);//模式串
        cin>>slen>>tlen;
        for(int i=0;i<slen;i++)
            scanf("%d",&S[i]);
        for(int i=0;i<tlen;i++)
            scanf("%d",&T[i]);
        ans=KMP_Index();    //模式串T在主串S中首次出现的位置,如果不存在,则输出-1
        if(ans==-1)
            cout<<-1<<endl;
        else
            cout<<ans+1<<endl;
    }
    return 0;
}

另外,可以通过next数组判断一个字符串是不是循环串(如abcabcabc)

如果next数组满足下面这个条件的话,表明是循环串:len%(len-nxt[len])==0

其中len是字符串的长度,len-nxt[len]是循环节的长度,len/(len-nxt[len])是循环的次数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值