一 原题
Hidden Password
Sometimes the programmers have very strange ways of hiding their passwords. Billy "Hacker" Geits chooses a string S composed of L (5 <= L <= 100,000) lowercase letters ('a'..'z') with length L. Then he makes and sorts all L-1 one-letter left cyclic shifts of the string. He then takes as a password one prefix of the lexicographically first of the obtained strings (including S).
For example consider the string "alabala". The sorted cyclic one-letter left shifts (including the initial string) are:
aalabal
abalaal
alaalab
alabala
balaala
laalaba
labalaa
Lexicographically, first string is 'aalabal'. The first letter of this string ('a') is the 'a' that was in position 6 in the initial string (counting the first letter in the string as position 0).
Write a program that, for given string S, finds the start position of the first letter of the sorted list of cyclic shifts of the string. If the first element appears more than once in the sorted list, then the program should output the smallest possible initial position.
PROGRAM NAME: hidden
INPUT FORMAT
- Line 1: A single integer: L
- Line 2..?: All L characters of the string S, broken across lines such that each line has 72 characters except the last one, which might have fewer.
SAMPLE INPUT (file hidden.in)
7 alabala
OUTPUT FORMAT
- Line 1: A single integer that is the start position of the first letter, as described above.
SAMPLE OUTPUT (file hidden.out)
6
二 分析
三 代码
USER: Qi Shen [maxkibb3] TASK: hidden LANG: C++ Compiling... Compile: OK Executing... Test 1: TEST OK [0.000 secs, 4244 KB] Test 2: TEST OK [0.000 secs, 4252 KB] Test 3: TEST OK [0.000 secs, 4248 KB] Test 4: TEST OK [0.000 secs, 4248 KB] Test 5: TEST OK [0.000 secs, 4244 KB] Test 6: TEST OK [0.000 secs, 4248 KB] Test 7: TEST OK [0.000 secs, 4252 KB] Test 8: TEST OK [0.000 secs, 4248 KB] Test 9: TEST OK [0.000 secs, 4244 KB] Test 10: TEST OK [0.000 secs, 4244 KB] Test 11: TEST OK [0.000 secs, 4248 KB] Test 12: TEST OK [0.000 secs, 4248 KB] Test 13: TEST OK [0.000 secs, 4248 KB] Test 14: TEST OK [0.000 secs, 4244 KB] All tests OK.
Your program ('hidden') produced all correct answers! This is your submission #19 for this problem. Congratulations!
/*
ID:maxkibb3
LANG:C++
PROB:hidden
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
const int MAX_LETTER_NUM = 2e5 + 10;
const int LETTER_PER_LINE = 72;
int min_representation(char *_s, int _len) {
memcpy(_s + _len, _s, _len);
int i = 0, j = 1;
while(i < _len && j < _len) {
int k = 0;
while(_s[i + k] == _s[j + k]) {
k++;
if(k == _len) return std::min(i, j);
}
if(_s[i + k] > _s[j + k]) i += k + 1;
if(_s[i + k] < _s[j + k]) j += k + 1;
if(i == j) j++;
}
if(j >= _len) return i;
else return j;
}
void solve() {
int len;
char s[MAX_LETTER_NUM] = {'\0'};
freopen("hidden.in", "r", stdin);
scanf("%d", &len);
char *ptr = s;
while(scanf("%s", ptr) != -1) {
ptr = ptr + 72;
}
memcpy(s + len, s, len);
freopen("hidden.out", "w", stdout);
printf("%d\n", min_representation(s, len));
}
int main() {
solve();
return 0;
}
运行结果2:
USER: Qi Shen [maxkibb3] TASK: hidden LANG: C++ Compiling... Compile: OK Executing... Test 1: TEST OK [0.000 secs, 10544 KB] Test 2: TEST OK [0.000 secs, 10544 KB] Test 3: TEST OK [0.000 secs, 10544 KB] Test 4: TEST OK [0.000 secs, 10544 KB] Test 5: TEST OK [0.000 secs, 10544 KB] Test 6: TEST OK [0.000 secs, 10544 KB] Test 7: TEST OK [0.028 secs, 10544 KB] Test 8: TEST OK [0.476 secs, 10544 KB] Test 9: TEST OK [0.504 secs, 10544 KB] Test 10: TEST OK [0.490 secs, 10544 KB] Test 11: TEST OK [0.294 secs, 10544 KB] Test 12: TEST OK [0.042 secs, 10704 KB] Test 13: TEST OK [0.000 secs, 10544 KB] Test 14: TEST OK [0.112 secs, 10860 KB] All tests OK.
Your program ('hidden') produced all correct answers! This is your submission #28 for this problem. Congratulations!
/*
TASK:hidden
ID:maxkibb3
LANG:C++
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
const int MAX = 2e5 + 10;
const int LETTER_PER_LINE = 72;
char Str[MAX];
int Len, Step;
int Bucket[MAX], BucketCopy[MAX];
struct Suffix {
int idx;
bool operator < (const Suffix &_o) const {
if(Step == 0) return Str[idx] < Str[_o.idx];
if(Bucket[idx] == Bucket[_o.idx])
return Bucket[idx + Step] < Bucket[_o.idx + Step];
else return Bucket[idx] < Bucket[_o.idx];
}
bool operator == (const Suffix &_o) const {
return !(*this < _o || _o < *this);
}
} Suf[MAX];
bool update_bucket() {
bool ret = true;
int cnt = 1;
for(int i = 0; i < Len; i++) {
if(i != 0 && !(Suf[i] == Suf[i - 1])) cnt++;
if(cnt == Len) ret = false;
BucketCopy[Suf[i].idx] = cnt;
}
memcpy(Bucket, BucketCopy, sizeof(BucketCopy));
return ret;
}
void suffix_sort(char *_s) {
for(int i = 0; i < Len; i++) Suf[i].idx = i;
// 当字符串相等时,题目要求输出最小下标,必须使用stable_sort
std::stable_sort(Suf, Suf + Len);
bool flag = update_bucket();
// Step的上界是输入字符串长度的一半
for(Step = 1; flag && Step <= Len / 4; Step *= 2) {
std::stable_sort(Suf, Suf + Len);
flag = update_bucket();
}
}
void init() {
freopen("hidden.in", "r", stdin);
freopen("hidden.out", "w", stdout);
scanf("%d", &Len);
for(int i = 0; ; i++) {
int tmp = scanf("%s", Str + LETTER_PER_LINE * i);
if(tmp == -1) break;
}
memcpy(Str + Len, Str, sizeof(char) * Len);
Len *= 2;
Str[Len] = '\0';
}
int main() {
init();
suffix_sort(Str);
for(int i = 0; ; i++)
if(Suf[i].idx < Len / 2) { printf("%d\n", Suf[i].idx); break; }
return 0;
}