题意:一个数字,依次将第一位放到最后一位,问小于本身的数的个数及等于本身的个数和大于本身的个数,但是要注意重复的不再计算
思路:用扩展KMP我们可以处理,先将串复制到后面一次,然后求扩展KMP,那么我们如何比较呢,如果extand[i]的值大于串的长度len,说明我以i为开头的串和原串的匹配大于len,也就说明这个串和原串相等,接下来就是另外两种情况,若extand[i]匹配到了第三位,那么久比较原串的第三位和以i开始的第三位即可,比较过后,处理重复的串,用KMP即可处理,如果串是一个以长度为len1的子串重复得来,那么最后结果便全部除以len1,画一下就一目了然了
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=200010;
int Next[maxn],extand[maxn];
char T[maxn];
void makenext(int m){
int i=0,j=-1;
Next[i]=-1;
while(i<m){
if(j==-1||T[i]==T[j])
Next[++i]=++j;
else j=Next[j];
}
}
void GetNext(const char *T){
int len=strlen(T),a=0;
extand[0]=len;
while(a<len-1&&T[a]==T[a+1]) a++;
extand[1]=a;
a=1;
for(int k=2;k<len;k++){
int p=a+extand[a]-1,L=extand[k-a];
if((k-1)+L>=p){
int j=(p-k+1)>0? (p-k+1):0;
while(k+j<len&&T[k+j]==T[j]) j++;
extand[k]=j;
a=k;
}
else extand[k]=L;
}
}
int main(){
int TT,t=1;
scanf("%d",&TT);
while(TT--){
scanf("%s",T);
int len=strlen(T);
makenext(len);
int k=len-Next[len];
int tt;
if(len%k==0) tt=len/k;
else tt=1;
for(int i=0;i<len;i++) T[len+i]=T[i];
GetNext(T);
int L=0,E=0,G=0;
for(int i=0;i<len;i++){
if(extand[i]>=len) E++;
else if(T[extand[i]]>T[i+extand[i]]) L++;
else if(T[extand[i]]<T[i+extand[i]]) G++;
}
printf("Case %d: %d %d %d\n",t++,L/tt,E/tt,G/tt);
}
return 0;
}