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;
}
posted @ 2017-04-06 15:54  forever97  阅读(98)  评论(0编辑  收藏  举报