String Problem HDU - 3374
考察: KMP+字符串的最小最大表示法
如果不懂字符串的最小最大表示法走这:GO (我认为是讲得很详细的)
当我们利用字符串的最小最大表示法求最小值和最大值下标后,直接利用next数组求循环节即可(如果最小/大值在循环字符串里出现多次,那么此字符串就可以构成循环节,并且循环节长度小于字符串长度一半)
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 const int N = 2000010; 6 char s[N],tmp[N]; 7 int len,ne[N]; 8 int get(int id) 9 { 10 int i = 1,j=2,k; 11 while(i<=len&&j<=len) 12 { 13 for(k=0;k<len&&tmp[i+k]==tmp[j+k];k++); 14 if(k==len) break; 15 if(tmp[i+k]>tmp[j+k]) 16 { 17 if(id) 18 { 19 i = i+k+1; 20 if(i==j) i++; 21 }else{ 22 j = j+k+1; 23 if(i==j) j++; 24 } 25 }else if(tmp[i+k]<tmp[j+k]) 26 { 27 if(id) 28 { 29 j = j+k+1; 30 if(i==j) j++; 31 }else{ 32 i = i+k+1; 33 if(i==j) i++; 34 } 35 } 36 } 37 int ans = min(i,j); 38 return ans; 39 } 40 int main() 41 { 42 while(scanf("%s",s+1)!=EOF) 43 { 44 len = strlen(s+1); 45 for(int i=1;i<=len;i++) tmp[len+i] = s[i],tmp[i] = s[i]; 46 tmp[len*2+1] = '\0'; 47 int l = get(1),r = get(0); 48 memset(ne,0,sizeof ne); 49 for(int i=2,j=0;i<=len;i++) 50 { 51 while(j&&s[j+1]!=s[i]) j = ne[j]; 52 if(s[j+1]==s[i]) j++; 53 ne[i] = j; 54 } 55 int lens = len-ne[len],cnt = 0; 56 if(len%lens==0) cnt = len/lens; 57 else cnt = 1; 58 printf("%d %d %d %d\n",l,cnt,r,cnt); 59 } 60 return 0; 61 }