字符串周期的问题
如果s1s2s3s4...sn = s3s4s5...sns1s2
那么说明s1=s2,s2=s3,s3=s4,s4=s5....
说明这个字符串是一个周期串。
更一般的情况是 s(i)s(i+1)...s(n)s(1)...s(i-1) = s(j)s(j+1)..s(n)s(1)...s(j-1) i!=j
那么说明以i开始的字符串是一个周期串。
题目:给我们一个字符串,要我们求它的最小表示,输出从哪个位置开始, 如果有多个, 那么返回最大的位置。
首先,用最小表示法求得开始位置最小的,然后用kmp求得循环节,然后强行移到最后。
当然了,也可以求出字典序最小的出现了多少次。
比如hdu3374
要求字典序最小和字典序最大的表示出现了多少次。
1 #pragma warning(disable:4996) 2 #include <iostream> 3 #include <stdio.h> 4 #include <string.h> 5 #include <math.h> 6 #include <string> 7 #include <vector> 8 #include <queue> 9 #include <set> 10 #include <map> 11 #include <algorithm> 12 #include <functional> 13 using namespace std; 14 15 const int N = 1000000 + 10; 16 char str[N]; 17 char tmp[N]; 18 int next[N]; 19 void getNext(char *str,int n) 20 { 21 int i = 0,j = -1; 22 next[0] = -1; 23 while(i<n) 24 { 25 if(j==-1||str[i]==str[j]) 26 { 27 ++i; 28 ++j; 29 next[i] = j; 30 } 31 else 32 j = next[j]; 33 } 34 } 35 36 int minimalRepresentation(char *str, int n) 37 { 38 int i = 0,j = 1, k = 0; 39 while(i<n && j<n && k<n) 40 { 41 int t = str[(i+k)%n] - str[(j+k)%n] ; 42 if(t == 0) 43 k++; 44 else 45 { 46 if(t>0) 47 i+=k+1; 48 else 49 j+=k+1; 50 if(i==j) 51 j++; 52 k = 0; 53 } 54 } 55 return i < j ? i : j; 56 } 57 int maxRepresentation(char *str, int n) 58 { 59 int i = 0,j = 1, k = 0; 60 while(i<n && j<n && k<n) 61 { 62 int t = str[(i+k)%n] - str[(j+k)%n] ; 63 if(t == 0) 64 k++; 65 else 66 { 67 if(t>0) 68 j+=k+1; 69 else 70 i+=k+1; 71 72 if(i==j) 73 j++; 74 k = 0; 75 } 76 } 77 return i < j ? i : j; 78 } 79 int solve(char *str, int n) 80 { 81 getNext(str,n); 82 return n/(n-next[n]);//n-next[n] 是周期 83 } 84 int main() 85 { 86 int idx1,times1,idx2,times2,n; 87 while(scanf("%s",str)!=EOF) 88 { 89 n = strlen(str); 90 idx1 = minimalRepresentation(str,n); 91 for(int i=0;i<n;++i) 92 tmp[i] = str[(i+idx1)%n]; 93 times1 = solve(tmp,n); 94 idx2 = maxRepresentation(str,n); 95 for(int i=0;i<n;++i) 96 tmp[i] = str[(i+idx2)%n]; 97 times2 = solve(tmp,n); 98 printf("%d %d %d %d\n",idx1+1,times1,idx2+1,times2); 99 100 } 101 return 0; 102 }