扩展kmp,先把原串翻一倍,然后构造原串的next数组,通过原串和原串翻倍的串构造extend数组,需要注意的是还要计算原串翻倍的串的循环节不然会超时!最后附上大神yefeng1627的扩展kmp的详细讲解及模板的博客(http://www.cnblogs.com/yefeng1627/archive/2012/12/24/2830979.html);
#include<stdio.h>
#include<string.h>
int next[200005],ext[200005],ans[4];
void mn(char *T)
{
int len=strlen(T),a,i;
next[0]=len;
a=1;
for(i=0;i<len-1&&T[i]==T[i+1];i++);
next[1]=i;
for(int k=2;k<len;k++)
{
int p=a+next[a]-1,l=next[k-a];
if((k-1)+l>=p)
{
int j=p-k+1>0?p-k+1:0;
while(k+j<len&&T[j]==T[j+k])
j++;
next[k]=j;
a=k;
}
else
next[k]=l;
}
}
void extend(char *S,char *T)
{
int lens=strlen(S),lent=strlen(T),a;
int ml=lens>lent?lent:lens;
a=0;
while(a<ml&&S[a]==T[a])
a++;
ext[0]=a;
a=0;
for(int k=1;k<lens;k++)
{
int p=a+ext[a]-1,l=next[k-a];
if((k-1)+l>=p)
{
int j=p-k+1>0?p-k+1:0;
while(k+j<lens&&j<lent&&T[j]==S[j+k])
j++;
ext[k]=j;
a=k;
}
else
ext[k]=l;
}
}
int fail[200005];
int kmp(char* str) {
int n = strlen(str);
int p =fail[0] = -1;
int j=0;
while(j<n) {
if(p==-1||str[p]==str[j])
{
p++;
j++;
fail[j]=p;
}
else
p=fail[p] ;
}
return n - fail[n];
}
int main()
{
char s[200005],t[200010];
int t1,kcas=0;
scanf("%d",&t1);
while(t1--)
{
scanf("%s",s);
int len=strlen(s);
strcpy(t,s);
strcat(t,s);
int ss=kmp(t);
// printf("%d\n",ss);
memset(next,0,sizeof(next));
mn(s);
extend(t,s);
int ans[3], tn = strlen(s);
memset(ans, 0, sizeof(ans));
for (int i = 0; i<ss; i++) {
if (ext[i] >= tn)
ans[1]++;
else {
int g = ext[i];
if (s[g] < t[i+g])
ans[2]++;
else
ans[0]++;
}
}
printf("Case %d: %d %d %d\n", ++kcas, ans[0], ans[1], ans[2]);
}
return 0;
}