[BZOJ3998]弦论

来源:互联网 发布:意式咖啡机推荐知乎 编辑:程序博客网 时间:2024/05/21 21:48

题目链接:BZOJ3998

题目大意
求长度为N的字符串的第K小子串。

分析
在后缀自动机上找第K小,用right集合的性质和dfs搞一搞就好了,可以自己YY一下。(意识流题解)

上代码

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 5e5 + 10;int len, T, K;int cnt, S, last;int ch[N << 1][26], link[N << 1], maxl[N << 1], rig[N << 1];inline void extend(int c) {    int now = ++cnt, tmp = last;    maxl[last = now] = maxl[tmp] + 1, rig[now] = 1;    for (; tmp && !ch[tmp][c]; tmp = link[tmp]) ch[tmp][c] = now;    if (!tmp) return link[now] = S, void(0);    if (maxl[ch[tmp][c]] == maxl[tmp] + 1)        return link[now] = ch[tmp][c], void(0);    int r = ++cnt, q = ch[tmp][c];    maxl[r] = maxl[tmp] + 1;    link[r] = link[q], link[q] = link[now] = r;    memcpy(ch[r], ch[q], sizeof(ch[q]));    for (; tmp && ch[tmp][c] == q; tmp = link[tmp]) ch[tmp][c] = r;}int dsc[N << 1], sum[N];void calcRig() {    for (int i = 1; i <= cnt; ++i) sum[maxl[i]]++;    for (int i = 1; i <= len; ++i) sum[i] += sum[i - 1];    for (int i = 1; i <= cnt; ++i) dsc[sum[maxl[i]]--] = i;    for (int i = cnt; i >= 1; --i) rig[link[dsc[i]]] += rig[dsc[i]];}int size[N << 1];void dfs(int a) {    if (size[a]) return;    size[a] = rig[a];    for (int i = 0; i < 26; ++i) {        int now = ch[a][i];        if (!now) continue;        dfs(now), size[a] += size[now];    }}void search(int a, int k) {    if (k > size[a]) puts("-1"), exit(0);    if (k -= rig[a], k <= 0) puts(""), exit(0);    for (int i = 0; i < 26; ++i) {        int now = ch[a][i];        if (!now) continue;        if (size[now] < k) k -= size[now];        else putchar(i + 'a'), search(now, k);    }}char ss[N];int main() {    S = cnt = last = 1;    scanf("%s", ss + 1), len = strlen(ss + 1);    for (int i = 1; i <= len; ++i) extend(ss[i] - 'a');    scanf("%d %d", &T, &K);    if (T) calcRig();    else for (int i = 2; i <= cnt; ++i) rig[i] = 1;    rig[S] = 0, dfs(S), search(S, K);    return 0;}

以上

0 0
原创粉丝点击