「TJOI2015」弦论

https://loj.ac/problem/2102
只是一道后缀自动机的题目
做法:首先当T=0时,就相当于从空串出发的有多少条路径,相当于每一个点都是1,然后dfs进行计数,在后缀自动机上进行贪心的输出就行了。
当T=1是,就相当于对于每一个非clone的点都为1 ,然后在建fail树,进行计数就可以了,再用dfs进行计数,在贪心的输出就可以了。

#include "bits/stdc++.h"

using namespace std;
typedef long long ll;
const int maxn = 1000000 + 10;
const int inf = 0x3f3f3f3f;
struct state {
    int len, link;
    int next[26];
//    unordered_map<int, int> next;
} st[maxn << 1];
ll wt[maxn], sum[maxn];
int sz, last;
void init() {
    st[0].len = 0;
    st[0].link = -1;
    sz++;
    last = 0;
}
void extend(int c) {
    int cur = sz++;
    st[cur].len = st[last].len + 1;
    wt[cur] = 1;
    int p = last;
    while (p != -1 && !st[p].next[c]) {
        st[p].next[c] = cur;
        p = st[p].link;
    }
    if (p == -1) {
        st[cur].link = 0;
    } else {
        int q = st[p].next[c];
        if (st[p].len + 1 == st[q].len) {
            st[cur].link = q;
        } else {
            int clone = sz++;
            st[clone].len = st[p].len + 1;
            memcpy(st[clone].next, st[q].next, sizeof(st[q].next));
//            st[clone].next = st[q].next;
            st[clone].link = st[q].link;
            while (p != -1 && st[p].next[c] == q) {
                st[p].next[c] = clone;
                p = st[p].link;
            }
            st[q].link = st[cur].link = clone;
        }
    }
    last = cur;
}
struct node {
    int v, nxt;
} ed[maxn];

int head[maxn], cnt = 0;
void add(int u, int v) {
    ++cnt;
    ed[cnt].v = v;
    ed[cnt].nxt = head[u];
    head[u] = cnt;
}

void dfs_cnt(int u) {
    for (int i = head[u]; i; i = ed[i].nxt) {
        dfs_cnt(ed[i].v);
        wt[u] += wt[ed[i].v];
    }
}

char str[maxn];
int t, k;

ll dfs(int now) {
    if (sum[now] > 0) return sum[now];
    sum[now] = wt[now];
    for (int i = 0; i < 26; i++) {
        if (st[now].next[i])
            sum[now] += dfs(st[now].next[i]);
    }
    return sum[now];
}

void print(int now, int k) {
    if (wt[now] >= k) return;
    else k -= wt[now];
    for (int i = 0; i < 26; i++) {
        if (st[now].next[i]) {
            if (sum[st[now].next[i]] >= k) {
                cout << char(i + 'a');
                print(st[now].next[i], k);
                return;
            }
            k -= sum[st[now].next[i]];
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    cin >> str;
    cin >> t >> k;
    int len = strlen(str);
    init();
    for (int i = 0; i < len; i++) {
        extend(str[i] - 'a');
    }
    if (t == 1) {
        for (int i = 1; i < sz; i++) add(st[i].link, i);
        dfs_cnt(0);

    } else {
        for (int i = 1; i < sz; i++) wt[i] = 1;
    }
    wt[0] = 0;
    dfs(0);
    if (sum[0] < k) cout << -1 << endl;
    else print(0, k);
    return 0;
}

发布了130 篇原创文章 · 获赞 80 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/KXL5180/article/details/103819003