http://acm.hdu.edu.cn/showproblem.php?pid=4333
对我来说这个题 太难了 看着标准程序敲的 伤不起呀
解析说是和KMP有关 不过已经变形的不成样子了 如果在比赛时做出了 你真的是牛神了
基本方法就是 先copy一个放在原串后面
依次求 以某处为开始点比较时原串要比较到的位置 位置超出字符串长度 说明相等
还要出来连续循环的情况 因为要找不同的数
#include<iostream> #include<cstdio> #include<cstdlib> #include<ctime> #include<queue> #include<cstring> #include<set> #include<cmath> #include<algorithm> #define LL long long using namespace std; const int N=200005; char s[N]; int next[N];//next 指向的是以此点开始的字符串应该与原串中的哪个字符进行比较 // 当然比较的时候此串也要找对应的字符进行比较 如果超过字符串长度 说明相等 void getnext(int n) { int l=1,r=-1;//l 和 r 代表循环串的左右位置 next[0]=0; for(int i=1;i<n;++i) { if(i+next[i-l]<=r) { next[i]=next[i-l];//如果前面对应的循环串对应位置字符要找的位置对应到本串中字符要找的位置没有超过r 说明可以直接将答案copy过来 }else { int j=max(r-i+1,0);//否则选择可以最靠后开始的位置进行依次比较 直到找到不同的 并记录循环串位置 for(;j+i<2*n;++j) if(s[j]!=s[i+j]) break; next[i]=j; l=i; r=i+j-1; } } } int main() { int T; //freopen("data.txt","r",stdin); scanf("%d",&T); getchar(); for(int c=1;c<=T;++c) { gets(s); int n=strlen(s); for(int i=0;i<n;++i) { s[i+n]=s[i]; } s[n*2]=0;//copy2 getnext(n); int i; for(i=1;i<n;++i) if(i+next[i]>=n) break;//找连续循环串位置 int m=(n%i)?m:i;?//如果可以除进 则只要环内部分 int l=0,q=1,g=0; for(i=1;i<m;++i) { if(next[i]>=n) { ++q; } else if(s[next[i]]>s[i+next[i]]) { ++l; }else { ++g; } } printf("Case %d: %d %d %d\n",c,l,q,g); } return 0; }