hdu 6153 A Secret【KMP/想法题】

来源:互联网 发布:瑞尔森大学怎么样知乎 编辑:程序博客网 时间:2024/06/05 05:29

题目

http://acm.hdu.edu.cn/showproblem.php?pid=6153

题意

给定两个串,求其中一个串 s 的每个后缀在另一个串 t 中出现的次数。

分析

后缀S(i..len)出现在后缀S(i-1…len)中,所以把两个串逆序后求KMP,这样从头扫到尾匹配一下,然后统计前缀出现的次数即可。

代码

#include <cstdio>#include <set>#include <iostream>#include <map>#include <vector>#include <cstring>#include <algorithm>#include <string>#include <cmath>using namespace  std;const int N=1e6+5;const int mod=1e9+7;typedef long long LL;char s[N],t[N];int slen,tlen;int nex[N];int num[N],vis[N];void getNext(){    int j,k;    j=0;k=nex[0]=-1;    while(j<tlen){        if(k==-1||t[j]==t[k])nex[++j]=++k;        else k=nex[k];    }}int KMP_Count(){    getNext();    int ans=0;    int j=0;    for(int i=0;i<slen;i++){        while(j&&s[i]!=t[j])j=nex[j];        if(s[i]==t[j]){            num[j]++;            j++;        }        if(j==tlen){            ans++;            j=nex[j];        }    }    return ans;}int main(){    int T;    scanf("%d",&T);    while(T--){        memset(num,0,sizeof(num));        memset(vis,0,sizeof(vis));        scanf("%s%s",s,t);        slen=strlen(s);        tlen=strlen(t);        for(int i=0;i<slen/2;i++)swap(s[i],s[slen-i-1]);        for(int i=0;i<tlen/2;i++)swap(t[i],t[tlen-i-1]);        KMP_Count();        for(int i=tlen;i>=0;i--){            if(!vis[nex[i]])num[nex[i]]+=num[i];            vis[nex[i]]=1;        }        LL ans=0;        for(int i=0;i<tlen;i++){            ans+=(LL)num[i]*(i+1);            ans%=mod;        }        cout<<ans<<endl;    }    return 0;}
原创粉丝点击