[JZOJ4624] 字符串匹配

来源:互联网 发布:python beaker 编辑:程序博客网 时间:2024/04/30 18:55

Description

给两个字符串S,T,求将T复制n次后S出现了多少次

Solution

咦,这不就kmp水题么。
先把T复制到比S长,跑一遍kmp
然后再整个复制一遍把中间的部分跑kmp,看会新组成多少。

然后除一下弄起来就好了。边上的细节要自己多想想(这是经典问题了,真的很水)

Code

#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>#include<algorithm>#include<iostream>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)using namespace std;char s[100005],t[400005];int p[100005],n,m,ans,ans1;long long cf,cs;long long kmp(int x,int y){    int i,j=0;    long long ans=0;    fo(i,x,y)    {        while (j>0&&s[j+1]!=t[i]) j=p[j];        if (s[j+1]==t[i]) j++;        if (j==n)         {            ans++;            j=p[j];        }    }    return ans;}void copy(){    int i;    fo(i,1,m) t[i+cs*m]=t[i];    cs++;}void copy1(){    int i;    fo(i,1,cs*m) t[i+cs*m]=t[i];    cs*=2;}int main(){    freopen("strmatch.in","r",stdin);    freopen("strmatch.out","w",stdout);    cin>>cf;    scanf("\n");    scanf("%s",s+1);    scanf("\n");    scanf("%s",t+1);    n=strlen(s+1);    m=strlen(t+1);    int i,j=0;    p[1]=0;    cs=1;    fo(i,2,n)    {        while (j>0&&s[j+1]!=s[i]) j=p[j];        if (s[j+1]==s[i]) j++;        p[i]=j;    }    if (cf*(long long)m<=3*n)    {        while (cs<cf) copy();        ans=kmp(1,cf*m);        cout<<ans;        return 0;    }    while (cs*m<n) copy();    ans=kmp(1,cs*m);    copy1();    ans1=kmp(cs*m/2-n+2,cs*m/2+n-1);    cs/=2;    long long s1=(cf/cs)*ans+(cf/cs-1)*ans1;    cout<<s1+(cf%cs==1)*ans;    }
0 0
原创粉丝点击