標籤:style blog http color os io ar div
題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=3374
題目大意:輸出最大和最小的是從哪一位開始的,同時輸出最小迴圈節的個數。
這裡簡單介紹對字串最小表示的方法:
(1) 利用兩個指標p1, p2。初始化時p1指向s[0], p2指向s[1]。
(2) k = 0開始,檢驗s[p1+k] 與 s[p2+k] 對應的字元是否相等,如果相等則k++,一直下去,直到找到第一個不同,(若k試了一個字串的長度也沒找到不同,則那個位置就是最小表示位置,演算法終止並返回)。則該過程中,s[p1+k] 與 s[p2+k]的大小關係,有三種情況:
(A). s[p1+k] > s[p2+k],則p1滑動到p1+k+1處 --- 即s1[p1->p1+k]不會是該迴圈字串的“最小表示”的首碼。 k置為0
(B). s[p1+k] < s[p2+k],則p2滑動到p2+k+1處, k置為0
(C). s[p1+k] = s[p2+k],則 k++; if (k == len) 返回結果。
注:這裡滑動方式有個小細節,若滑動後p1 == p2,將正在變化的那個指標再+1。直到p1、p2把整個字串都檢驗完畢,返回兩者中小於 len 的值。
(3) 如果 k == len, 則返回p1與p2中的最小值
最大和最小表示完全類似,簡單的改變一下即可。下面詳見代碼。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 int next[1000010],len,t; 6 char ch[1000010]; 7 8 void get_next() 9 {10 int i=0,j=-1;11 next[0]=-1;12 while (i<len)13 {14 if (j==-1||ch[i]==ch[j])15 {16 i++;17 j++;18 next[i]=j;19 }20 else21 j=next[j];22 }23 }24 25 int Min_(char s[],int len)26 {27 int p1=0,p2=1,k=0;28 while (p1<len&&p2<len&&k<len)29 {30 t=s[(p1+k)%len]-s[(p2+k)%len];31 if (t==0)32 k++;33 else34 {35 if (t>0)36 p1=p1+k+1;37 else38 p2=p2+k+1;39 if (p1==p2)40 p2++;41 k=0;42 }43 }44 return min(p1,p2);45 }46 47 int Max_(char s[],int len)48 {49 int p1=0,p2=1,k=0;50 while (p1<len&&p2<len&&k<len)51 {52 t=s[(p1+k)%len]-s[(p2+k)%len];53 if (t==0)54 k++;55 else56 {57 if (t>0)58 p2=p2+k+1;59 else60 p1=p1+k+1;61 if (p1==p2)62 p2++;63 k=0;64 65 }66 }67 return p1<p2?p1:p2;68 }69 70 int main()71 {72 while(~scanf("%s",ch))73 {74 len=strlen(ch);75 get_next();76 int Max=Max_(ch,len);77 int Min=Min_(ch,len);78 //cout<<Max<<Min<<endl;79 int sum=0;80 if(len%(len-next[len])==0)81 sum=len/(len-next[len]);82 else83 sum=1;84 printf ("%d %d %d %d\n",Min+1,sum,Max+1,sum);85 }86 return 0;87 }