標籤:
Description:
Give you a string with length N, you can generate N strings by left shifts. For example let consider the string “SKYLONG”, we can generate seven strings:
String Rank
SKYLONG 1
KYLONGS 2
YLONGSK 3
LONGSKY 4
ONGSKYL 5
NGSKYLO 6
GSKYLON 7
and lexicographically first of them is GSKYLON, lexicographically last is YLONGSK, both of them appear only once.
Your task is easy, calculate the lexicographically fisrt string’s Rank (if there are multiple answers, choose the smallest one), its times, lexicographically last string’s Rank (if there are multiple answers, choose the smallest one), and its times also.
Input:
Each line contains one line the string S with length N (N <= 1000000) formed by lower case letters.
Output:
Output four integers separated by one space, lexicographically fisrt string’s Rank (if there are multiple answers, choose the smallest one), the string’s times in the N generated strings, lexicographically last string’s Rank (if there are multiple answers, choose the smallest one), and its times also.
Sample Input:
abcderaaaaaaababab
Sample Output:
1 1 6 11 6 1 61 3 2 3 題意:一個長度為n的字串,通過每次迴圈移位可以得到n個字串,那麼現在需要輸出字典序最小的那個字串出現的位置及其出現的次數,還有字典序最大的字串出現的最早位置及其出現的次數,新的方法(最大最小表示)。
#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;const int N=1e6+10;char s[N*2], a[N]; ///s存放兩個a字串,供迴圈移位時需要int Next[N], la;void Getnext() ///這個Next數組存放a的Next值{ int i = 0, j = -1; Next[0] = -1; while (i <= la) { if (j == -1 || a[i] == a[j]) { i++; j++; Next[i] = j; } else j = Next[j]; }}int GetMin() ///求出字典序最小的字串最早出現的位置{ int i = 0, j = 1, k; ///這裡i!=j,可以將s[i+k]和s[j+k]分別看做兩個字串的首字元(相當於在判斷兩個字串的大小) while (i < la && j < la) { k = 0; ///k記錄字元相等的個數 while (s[i+k] == s[j+k] && k < la) k++; if (k == la) break; ///若是la個字元都相等,那麼可以確定兩個字串都是最小的,已經找到最小,停止尋找 if (s[i+k] > s[j+k]) ///因為是求最小的,所以大的那個下標要後移,而小的值不變(類似求最小值,一直更新) { if (i+k > j) i = i+k+1; else i = j+1; } else { if (j+k > i) j = j+k+1; else j = i+1; } } return min(i, j); ///因為要最早,所以求最小值}int GetMax() ///求出字典序最大的字串最早出現的位置{ int i = 0, j = 1, k; while (i < la && j < la) { k = 0; while (s[i+k] == s[j+k] && k < la) k++; if (k == la) break; if (s[i+k] > s[j+k]) ///那麼這裡就是小的值向後移,大的值不變了 { if (j+k > i) j = j+k+1; else j = i+1; } else { if (i+k > j) i = i+k+1; else i = j+1; } } return min(i, j);}int main (){ int x, Time, Miid, Maid; ///x記錄迴圈節的長度,Time記錄出現的次數 while (scanf("%s", a) != EOF) { strcpy(s, a); strcat(s, a); la = strlen(a); Getnext(); x = la - Next[la]; Time = la / x; ///可以得出最小值和最大值出現次數都為迴圈節的個數 Miid = GetMin(); Maid = GetMax(); printf("%d %d %d %d\n", Miid+1, Time, Maid+1, Time); ///因為下標都是從0開始的,所以要加1 } return 0;}
HDU 3374 String Problem(最大最小表示)