原题链接
思路比较简单。把原串扩大一倍,然后以原串为模板串,用扩展kmp算法求出每个位置的最大前缀即可。(WA了一天了,也不知道改了哪个地方就对了…………)
#include<iostream>
#include<cstdio>
#define maxl 1000100
using namespace std;
char s1[maxl*2],s2[maxl*2];
int len,pre[maxl],temp;
void getpre(char*s){
pre[1]=pre[0]=0;
for(int i=1;i<len;i++){
int j=pre[i];
while(j&&s[i]!=s[j])j=pre[j];
pre[i+1]=s[i]==s[j]?j+1:0;
}
temp=len%(len-pre[len])==0?len/(len-pre[len]):1;
s[len]='\0';
}
void getst(){
len=0;
for(char c=getchar();c!='\n'&&c!=' '&&c!=EOF;c=getchar()){
s2[len]=s1[len]=c;
len++;
}
getpre(s1);
for(int i=len;i<2*len;i++)s2[i]=s1[i-len];
s2[2*len]='\0';
}
int f[maxl];
void getf(char*s,int*f){
f[0]=len,f[1]=len-1;
for(int i=0;i<len;i++)if(s[i]!=s[i+1]){f[1]=i;break;}
int k=1;
for(int i=2;i<=len;i++){
int p=k+f[k]-1,l=f[i-k];
if(i+l<=p)f[i]=l;else{
int j=max(0,p-i+1);
while(i+j<len&&s[i+j]==s[j])j++;
f[i]=j;
k=i;
}
}
}
int ex[maxl];
void exkmp(char*T,char*P){
getf(P,f);
ex[0]=ex[1]=len;
for(int i=0;i<len;i++)if(P[i]!=T[i+1]){ex[1]=i;break;}
int k=1;
for(int i=2;i<len;i++){
int p=k+ex[k]-1,l=f[i-k];
if(i+l<=p)ex[i]=l;else{
int j=max(0,p-i+1);
while(i+j<2*len&&T[i+j]==P[j])j++;
ex[i]=j;k=i;
}
}
}
int main(){
freopen("4333.in","r",stdin);
freopen("wode.out","w",stdout);
int T;
scanf("%d",&T);
getchar();
for(int j=1;j<=T;j++){
getst();
exkmp(s2,s1);
int c1=0,c2=0,c3=0;
for(int i=0;i<len;i++)if(ex[i]>=len)c1++;
else if(s2[i+ex[i]]<s1[ex[i]])c2++;
else c3++;
printf("Case %d: %d %d %d\n",j,c2/temp,c1/temp,c3/temp);
}
return 0;
}