hdu4333
/* 题意:字符串s[0..n-1],每次把最后一个字符放到前面,求形成的字符串比最初串分别小,相同,大于的个数 因为是为了练习扩展KMP所以肯定是扩展KMP, 为了循环方便,在后面复制字符串,求出next[]数组后, 如果next[i]>n那么肯定相等,如果小于就判断s[ next[i] ]和 s[ i+next[i] ]的大小判断 trick:题目求得是形成的不同的字符串的个数,可以知道相等的字符串肯定只有一个, 而从0..n-1,第二个next[i]大于n那么这个i就是该字符串的循环节; */ #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<cmath> #include<vector> #include<algorithm> using namespace std; const int N=100000+10; char s[N*2]; int next[N*2],n; void getNext(char *s,int next[]){ int nn=strlen(s); next[0]=nn; int p=0; while (s[p+1] && s[p]==s[p+1]) p++; next[1]=p; int k=1; for (int i=2;i<nn;i++){ int p=k+next[k]-1, L=next[i-k]; if (i+L<=p) next[i]=L; else{ int j=p-i+1; if (j<0) j=0; while (i+j<nn && s[i+j]==s[j]) j++; next[i]=j; k=i; } } } void work(){ int ret1,ret2,ret3; ret1=ret2=ret3=0; getNext(s,next); for (int i=0;i<n;i++){ if (i!=0 && next[i]>=n) break; if (next[i]<n) { if (s[ i+next[i] ]<s[ next[i] ]) ret1++; else ret3++; }else ret2++; } printf("%d %d %d ",ret1,ret2,ret3); } int main(){ int T,cas=0;scanf("%d",&T); while (T--){ scanf("%s",s); printf("Case %d: ",++cas); n=strlen(s); for (int i=0;i<n;i++){ s[n+i]=s[i]; }s[n+n]='