hdoj 5442 Favorite Donut 【KMP最大表示法 后缀数组】

来源:互联网 发布:excel2007数据库驱动 编辑:程序博客网 时间:2024/06/08 00:34

题目链接:hdoj 5442 Favorite Donut

近来去预习了一发KMP,发现一剩题。

题意:给定一个长度为n的首尾相接的字符串,你可以顺时针找到n个串,逆时针找到n个串。问你所有串中字典序最大的串,若有多个则输出起点最小的,若依然有多少个,优先输出顺时针。

正反跑一次最大表示法,反着的就先找到那个字典序最大的串,跑一次KMP,找到最近的位置。然后比较即可。

其实可以用后缀数组,我们先copy串,然后处理出sa 和 height。
正的情况就是,从sa[] < n的情况下,倒着找到最后那个满足height[i] >= n的串。
反的情况就是,从sa[] < n的情况下,倒着找到最开始的满足height[i] >= n的串。
懒,不上后缀数组代码了。

#include <iostream>#include <cstdlib>#include <cstdio>#include <algorithm>#include <string>#include <map>#include <cstring>#include <stack>#include <queue>#include <cmath>#include <vector>#include <set>#define ll o<<1#define rr o<<1|1using namespace std;typedef long long LL;typedef pair<int, int> pii;const int MAXN = 2e4 + 10;const int MAXM = 1e5 + 10;const int MOD = 1e9 + 7;void add(LL &x, LL y) { x = (x + y) % MOD; }char str[2 * MAXN];int len;int getMax() {    int i = 0, j = 1, k = 0;    while (i < len && j < len && k < len) {        int t = str[(i + k) % len] - str[(j + k) % len];        if (!t) k++;        else {            if (t > 0) {                if (j + k + 1 > i) j = j + k + 1;                else j = i + 1;            }            else if (i + k + 1 > j) i = i + k + 1;            else i = j + 1;            k = 0;        }    }    return i < j ? i : j;}char s1[MAXN], s2[MAXN];int nextn[MAXN];void getnextn() {    int j = -1, i = 0; nextn[i] = j;    int l = strlen(s2);    while(i < l) {        if(j == -1 || s2[i] == s2[j]) {            i++; j++;            nextn[i] = j;        }        else {            j = nextn[j];        }    }}int kmp() {    int id; getnextn();    int l1 = strlen(str);    int l2 = strlen(s2);    int j = 0, i = 0;    while(i < l1) {        if(j == -1 || str[i] == s2[j]) {            i++; j++;            if(j == l2) {                id = i - l2;            }        }        else {            j = nextn[j];        }    }    return id;}int main(){    int t; scanf("%d", &t);    while(t--) {        scanf("%d%s", &len, str);        int id1 = getMax();        int j = 0;        for(int i = id1; i < len; i++) {            s1[j++] = str[i];        }        for(int i = 0; i < id1; i++) {            s1[j++] = str[i];        }        s1[j] = 0;        strrev(str);        int id2 = getMax();        j = 0;        for(int i = id2; i < len; i++) {            s2[j++] = str[i];        }        for(int i = 0; i < id2; i++) {            s2[j++] = str[i];        }        s2[j] = 0;        j = len;        for(int i = len; i < 2 * len - 1; i++) {            str[j++] = str[i - len];        }        str[j] = 0;        id2 = len - kmp(); id1++;        if(strcmp(s1, s2) > 0) {            printf("%d %d\n", id1, 0);        }        else if(strcmp(s1, s2) < 0) {            printf("%d %d\n", id2, 1);        }        else {            if(id1 > id2) {                printf("%d %d\n", id2, 1);            }            else {                printf("%d %d\n", id1, 0);            }        }    }    return 0;}
0 1