zoj2587 Marlon's String

来源:互联网 发布:网购联盟和淘宝联盟 编辑:程序博客网 时间:2024/05/21 11:30

KMP

求子串的每个前缀在母串中出现的次数,然后反转再求一次,然后计算结果即可

PS:ZOJ评测好严格啊,不强制转换类型会WA。。。就因为这个WA了好久。。。一定不要偷懒啊!!!

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#define N 100050using namespace std;int jump[N],ans1[N],ans2[N];char s1[N],s2[N],t1[N],t2[N];void init(char *t){    jump[0]=-1;    int j=-1,len=strlen(t);    for(int i=1;i<len;i++)    {        while(j>-1&&t[i]!=t[j+1])j=jump[j];        if(t[i]==t[j+1])j++;        jump[i]=j;    }}void kmp(char *s,char *t){    int j=-1,len=strlen(s),len2=strlen(t);    for(int i=0;i<len;i++)    {        while(j>-1&&s[i]!=t[j+1])j=jump[j];        if(s[i]==t[j+1]){j++;ans1[j]++;}        //if(j==len2-1)        //{           // printf("%d\n",i-len2+1);        //}    }}void kmp2(char *s,char *t){    int j=-1,len=strlen(s),len2=strlen(t);    for(int i=0;i<len;i++)    {        while(j>-1&&s[i]!=t[j+1])j=jump[j];        if(s[i]==t[j+1]){j++;ans2[j]++;}        //if(j==len2-1)        //{           // printf("%d\n",i-len2+1);        //}    }}int main(){    int tc,len1,len2;    long long ans;    scanf("%d",&tc);    getchar();    while(tc>0)    {       tc--;       memset(ans1,0,sizeof(ans1));       memset(ans2,0,sizeof(ans2));       gets(s1);       gets(s2);       len1=strlen(s1),len2=strlen(s2);       init(s2);       kmp(s1,s2);       for(int i=len2-1;i>=0;i--)if(jump[i]!=-1)ans1[jump[i]]+=ans1[i];                     //这个要注意       t1[len1]='\0';t2[len2]='\0';       for(int i=len1-1;i>=0;i--)t1[len1-i-1]=s1[i];       for(int i=len2-1;i>=0;i--)t2[len2-i-1]=s2[i];       init(t2);       kmp2(t1,t2);       for(int i=len2-1;i>=0;i--)if(jump[i]!=-1)ans2[jump[i]]+=ans2[i];                     //这个要注意       ans=0;       //for(int i=0;i<len2;i++)printf("%d\n",ans1[i]);       //cout<<endl;       //for(int i=0;i<len2;i++)printf("%d\n",ans2[i]);       for(int i=0;i<len2-1;i++)ans+=(long long)ans1[i]*(long long)ans2[len2-i-2];          //一定要强制类型转换啊,切记!!       printf("%lld\n",ans);    }    return 0;}



原创粉丝点击