HDU 4333 Revolving Digits(扩展kmp)
【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=4333
【题目大意】
给出一个数字,每次将其最后一位提到最前面来,问产生的所有数字中,
有多少比原数大,有多少比原数小,有多少和原数相等
【题解】
我们发现比较字符串形式的两个数的大小,只要比较他们LCP后的第一位即可
我们用exkmp处理LCP的方式处理两倍长原串,然后顺次枚举记录答案即可。
【代码】
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int N=500010; int len,LCP[N],ex1[N],ex2[N],a[N],s[N]; char S[N],T[N]; void getLCP(char *T){ int i,len=strlen(T); LCP[0]=len; for(i=0;i<len-1&&T[i]==T[i+1];i++); LCP[1]=i; int a=1; for(int k=2;k<len;k++){ int p=a+LCP[a]-1,L=LCP[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++; LCP[k]=j,a=k; }else LCP[k]=L; } } int main(){ int Cas; scanf("%d",&Cas); for(int cas=1;cas<=Cas;cas++){ int L=0,E=0,G=0; scanf("%s",S); int len=strlen(S); for(int i=0;i<len;i++)S[len+i]=S[i]; S[len*2]='\0'; getLCP(S); for(int i=0;i<len;i++){ //printf("%d %c %c\n",LCP[i],S[LCP[i]],S[LCP[i]+i]); if(LCP[i]>=len)E++; else if(S[LCP[i]]<S[LCP[i]+i])G++; else L++; }printf("Case %d: %d %d %d\n",cas,L/E,E/E,G/E); }return 0; }
愿你出走半生,归来仍是少年