usaco5.5.2 Hidden Password

来源:互联网 发布:js大禹防水涂料 编辑:程序博客网 时间:2024/05/19 12:29

一 原题

Hidden Password

ACM South Eastern Europe -- 2003

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)

7alabala

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

二 分析

裸的字符串最小表示法,时间复杂度O(n)。


三 代码

运行结果:
USER: Qi Shen [maxkibb3]TASK: hiddenLANG: C++Compiling...Compile: OKExecuting...   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 yoursubmission #19 for this problem. Congratulations!


AC代码:
/*ID:maxkibb3LANG: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: hiddenLANG: C++Compiling...Compile: OKExecuting...   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 yoursubmission #28 for this problem. Congratulations!


AC代码2(后缀数组):
/*TASK:hiddenID:maxkibb3LANG: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;}



原创粉丝点击