题目链接:BZOJ3998
题目大意
求长度为
N
的字符串的第
分析
在后缀自动机上找第
K
小,用
上代码
#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;
}
以上