Revolving Digits(hdu 4333)

题意:就是给你一个数字,然后把最后一个数字放到最前面去,经过几次变换后又回到原数字,问在这些数字中,比原数字小的,相等的,大的分别有多少个。比如341-->134-->413-->341,所以和原数字相比,比原数字小的有一个,相等的有一个,大的有一个。

/*
  如果比较两个字符串,就比较第一位不一样的,那我们就需要找出所有字符串和已知字符串的前缀公共部分。
  在已知字符串后面载copy一份,然后做exkmp就行了。
  需要注意的是,相同字符串只能出现一次,所以先求一遍循环节。 
有一篇关于exkmp的ppt:http://wenku.baidu.com/view/79992a90bed5b9f3f80f1c16.html?from=search
*/ #include<cstdio> #include<iostream> #include<cstring> #define N 200100 using namespace std; int Next[N],cas; char T[N]; void kmp(int m){ int i=0,j=-1; Next[i]=-1; while(i<m){ if(j==-1||T[i]==T[j]){ i++;j++;Next[i]=j; } else j=Next[j]; } } void get_Next(){ int a=0,Tlen=strlen(T); Next[0]=Tlen; while(a<Tlen-1&&T[a]==T[a+1])a++; Next[1]=a; a=1; for(int k=2;k<Tlen;k++){ int p=a+Next[a]-1,L=Next[k-a]; if(k-1+L>=p){ int j=(p-k+1>0)?p-k+1:0; while(k+j<Tlen&&T[k+j]==T[j])j++; Next[k]=j; a=k; } else Next[k]=L; } } int main(){ int t;scanf("%d",&t); while(t--){ scanf("%s",T); int len=strlen(T); kmp(len); int k=len-Next[len],tt; if(len%k==0)tt=len/k; else tt=1; for(int i=0;i<len;i++) T[len+i]=T[i]; get_Next(); int num1=0,num2=0,num3=0; for(int i=0;i<len;i++){ if(Next[i]>=len)num2++; else if(T[Next[i]]>T[i+Next[i]])num1++; else if(T[Next[i]]<T[i+Next[i]])num3++; } printf("Case %d: %d %d %d ",++cas,num1/tt,num2/tt,num3/tt); } return 0; }

原文地址:https://www.cnblogs.com/harden/p/6250054.html