一 原题
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;
}

博客介绍了如何从字符串的字典序排列中找到隐藏密码的起始位置,即找到排序后的第一个字符串的第一个字符在原字符串中的位置。题目来源于ACM South Eastern Europe 2003竞赛,给出字符串S,需要找出所有左循环移位排序后的前缀,并返回最小的起始位置。
441

被折叠的 条评论
为什么被折叠?



