Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 25512 Accepted Submission(s): 5585
如果比较两个字符串,就比较第一位不一样的,那我们就需要找出所有字符串和已知字符串的前缀公共部分。
在已知字符串后面载copy一份,然后做exkmp就行了。
需要注意的是,相同字符串只能出现一次,所以先求一遍循环节。
有一篇关于exkmp的ppt:http://wenku.baidu.com/view/79992a90bed5b9f3f80f1c16.html?from=search
#include<cstdio> #include<cstring> using namespace std; const int N=2e5+10; int cas,_,Next[N]; char T[N]; void kmp(int l){ int i=0,j=-1;Next[i]=j; while(i<l){ if(j==-1||T[i]==T[j]) Next[++i]=++j; else j=Next[j]; } } void get_next(int Tlen){ int a=0; Next[0]=Tlen; while(a<Tlen-1&&T[a]==T[a+1]) a++; Next[1]=a;a=1; for(int k=2;k<Tlen;k++){ int p=a+Next[a]-1,L=Next[k-a]; if(k+L-1>=p){ int j=(p-k+1>0)?p-k+1:0; while(k+j<Tlen&&T[k+j]==T[j]) j++; Next[k]=j;a=k; } else Next[k]=L; } } int main(){ for(scanf("%d",&_),cas=1;cas<=_;cas++){ scanf("%s",T); int len=strlen(T); kmp(len); int k=len-Next[len],tt; if(len%k==0) tt=len/k; else tt=1; for(int i=0;i<len;i++) T[len+i]=T[i]; get_next(len*2); int num1=0,num2=0,num3=0; for(int i=0;i<len;i++){ if(Next[i]>=len) num2++; else if(T[Next[i]]>T[i+Next[i]]) num1++; else if(T[Next[i]]<T[i+Next[i]]) num3++; } printf("Case %d: %d %d %d\n",cas,num1/tt,num2/tt,num3/tt); } return 0; }
原文:http://www.cnblogs.com/shenben/p/6253935.html