题解:
EX_KMP
先把串复制一遍放到后面
这样旋转就是每一个前缀了
然后做一个EX_KMP
然后看一下后一个字符谁大谁小
代码:
#include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; #define next ____next const int N=200005; char s[N]; int T,next[N],cas; void getnext(char *a,int len) { int i=-1,j=0; next[0]=-1; while (j<len) { if (i==-1||a[i]==a[j])next[++j]=++i; else i=next[i]; } } void getex(char *a,int len) { int k=0,i=1; next[0]=len; while (k+1<len&&a[k]==a[k+1])k++; next[1]=k; k=1; while (++i<=len/2) { int maxr=next[k]+k-1; next[i]=min(next[i-k],max(0,maxr-i+1)); while (i+next[i]<len&&a[next[i]]==a[next[i]+i])next[i]++; if (i+next[i]>k+next[k])k=i; } } int main() { scanf("%d",&T); while (T--) { scanf("%s",&s); int len=strlen(s); getnext(s,len); int tmp=len%(len-next[len])==0?len/(len-next[len]):1; for (int i=0;i<=len;i++)s[i+len]=s[i]; getex(s,len*2); int a=0,b=0,c=0; for (int i=0;i<len;i++) { if (next[i]>=len)b++; else if (s[next[i]+i]>s[next[i]])c++; else a++; } printf("Case %d: %d %d %d ",++cas,a/tmp,b/tmp,c/tmp); } }