题意:题意:给定一个数字<=10^100000,一次将该数的第一位放到放到最后一位,求所有组成的不同的数比原数小的个数,相等的个数,大的个数
扩展kmp入门题
假如有431,则复制为2个,即,431431,
对该字符串和原穿求ekmp求得extend,求得最长公共前缀,3,0,0,3,0,0,extend【1】=3即表示匹配3位则刚好为原串的长度,则相等,extend【2】=0表示并未存在相同前缀,这时就拿3和4比较,假设extend【2】=1,即存在一个相同前缀,那么只需要和第二位比较即可。
总体来说就是避免不必要的比较
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 const int MAXN=2000010; 10 11 int nextt[MAXN]; 12 int extend[MAXN]; 13 14 void pre_EKMP(char x[],int m,int nextt[]) 15 { 16 nextt[0]=m; 17 int j=0; 18 while(j+1<m && x[j]==x[j+1])j++; 19 nextt[1]=j; 20 int k=1; 21 for(int i=2;i<m;i++) 22 { 23 int p=nextt[k]+k-1; 24 int L=nextt[i-k]; 25 if(i+L<p+1)nextt[i]=L; 26 else 27 { 28 j=max(0,p-i+1); 29 while(i+j<m && x[i+j]==x[j])j++; 30 nextt[i]=j; 31 k=i; 32 } 33 } 34 } 35 void EKMP(char x[],char y[]) 36 { 37 int n=strlen(y); 38 int m=strlen(x); 39 pre_EKMP(x,m,nextt); 40 int j=0; 41 while(j<n && j<m && x[j]==y[j])j++; 42 extend[0]=j; 43 int k=0; 44 for(int i=1;i<n;i++) 45 { 46 int p=extend[k]+k-1; 47 int L=nextt[i-k]; 48 if(i+L<p+1)extend[i]=L; 49 else 50 { 51 j=max(0,p-i+1); 52 while(i+j<n && j<m && y[i+j]==x[j])j++; 53 extend[i]=j; 54 k=i; 55 } 56 } 57 } 58 void getnextt(char T[],int len) 59 { 60 int j,k; 61 j=0;k=-1; 62 nextt[0]=-1; 63 while(j<len) 64 { 65 if(k==-1 || T[j]==T[k]) 66 nextt[++j]=++k; 67 else k=nextt[k]; 68 } 69 } 70 char str1[MAXN],str2[MAXN]; 71 int main() 72 { 73 #ifndef ONLINE_JUDGE 74 freopen("1.in","r",stdin); 75 #endif 76 int T; 77 int iCase=0; 78 scanf("%d",&T); 79 while(T--) 80 { 81 iCase++; 82 scanf("%s",str1); 83 int len=strlen(str1); 84 strcpy(str2,str1); 85 strcat(str2,str1); 86 EKMP(str1,str2); 87 /*for(int i=0;i<len*2;i++) 88 { 89 printf("%d ",extend[i]); 90 } 91 printf(" ");*/ 92 int cnt1=0,cnt2=0,cnt3=0; 93 for(int i=0;i<len;i++) 94 { 95 if(extend[i]>=len)cnt2++; 96 else 97 { 98 if(str2[i+extend[i]]<str1[extend[i]])cnt1++; 99 else cnt3++; 100 } 101 } 102 getnextt(str1,len); 103 int t=len-nextt[len]; 104 int tol=1; 105 if(len%t==0)tol=len/t; 106 printf("Case %d: %d %d %d ",iCase,cnt1/tol,cnt2/tol,cnt3/tol); 107 } 108 return 0; 109 }