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;
}