1. 程式人生 > >【POJ1509】Glass Beads

【POJ1509】Glass Beads

pri i+1 字典序 lse tdi 暴力 時間復雜度 scanf 字符串

【POJ1509】Glass Beads

【題目描述】給定字符串S,並規定首尾相連成環,求出最小字典序。

【輸入】輸入有多個數據,第一行只包括正整數N,表示有N組數據。每個數據包括一行,輸入該字符串。

【輸出】對於每個數據,輸出一行數據表示從哪一個字母開始為最小字典序排列。

【題解思路】暴力是個好東西,咳咳咳

該題為赤果果的最小表示。

Q:最小表示是什麽?

A:看題目描述撒。

Q:怎麽個表示法呢?

A:莫急,往下看哈。

  • 還是從暴力開始講:依次比較n個以不同位置字符開頭的字符串,找到其中字典序最小的那一個。復雜度…貌似是O(n^3)的吧。

  • 考慮暴力比較時的過程:設以i開頭的字符串串為A[i],比較A[i+k]與A[j+k](0<=k<=n)是否相等,找到不相等的地方,判斷該位置上的元素哪個字典序大那麽以該序列開頭的串串整體字典序就比較大。

  • 再次考慮剛剛的暴力過程。如果我們發現i+k與j+k不相等,不妨設是i+k處字典序大於j+k處字典序,那麽A[i]肯定不是最小表示。其次,對於A[i+p]和A[j+p], A[j+p]始終會比A[i+p]更優。因為兩個串串進行比較會在p = k時不等,而i+k處的字典序又大於j+k處的,A[j+p]的字典序總是小於A[i+p]。那麽當我們能判斷一組這樣的關系時,滿足編號差為相同值的任意兩個串都滿足同樣的關系。

  • 具體思路:

(1) 從i = 1,j = 2開始往後掃描,若掃描了n個字符串之後仍然相等,說明S只由1種字符構成,那麽輸出數字1即可;

(2) 若在i+k與j+k處發現不等,若A[i+k]>A[j+k],令i = i+k+1。若此時i = j,再令i = i+1。若A[i+k]<A[j+k],令j = j+k+1。若此時i = j,再令j = j+1;

(3) 掃描完之後,若i>n,A[j]為最小表示,若j>n,A[i]為最小表示。

該算法時間復雜度為O(n)。

技術分享圖片
 1 #include<iostream>
 2 #include<string.h>
 3 #include<cstdio>
 4 const int maxs = 1e4+5;
 5 using namespace std;
 6 int n,ans;
 7 char s[maxs*2];
 8 int main(){
 9     scanf("%d",&n);
10     while(n--){
11         scanf("
%s",s+1); 12 int lens = strlen(s+1); 13 for(int i = 1;i <= lens; ++i) s[lens+i] = s[i]; 14 int i = 1,j = 2,k; 15 while(i <= lens && j <= lens){ 16 for(k = 0;k <= lens && s[i+k]==s[j+k]; k++); 17 if(k >= lens) break; 18 if(s[i+k] > s[j+k]){ 19 i = i+k+1; 20 if(i == j) i++; 21 } else{ 22 j = j+k+1; 23 if(i == j) j++; 24 } 25 } 26 ans = min(i,j); 27 printf("%d\n",ans); 28 } 29 return 0; 30 }
View Code

【POJ1509】Glass Beads