結果
| 問題 |
No.3188 K-th Lexmin
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2025-06-20 22:46:46 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 1,039 ms / 3,500 ms |
| コード長 | 4,115 bytes |
| コンパイル時間 | 2,568 ms |
| コンパイル使用メモリ | 218,124 KB |
| 実行使用メモリ | 63,340 KB |
| 最終ジャッジ日時 | 2025-08-13 09:04:32 |
| 合計ジャッジ時間 | 42,416 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 47 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
struct SuffixAutomaton {
struct State {
int len, link;
map<int, int> next;
};
vector<State> st;
vector<ll> occ, tot;
int last;
SuffixAutomaton(int maxlen = 0) {
st.reserve(2 * maxlen);
occ.reserve(2 * maxlen);
tot.reserve(2 * maxlen);
clear();
}
void clear() {
st.clear();
occ.clear();
tot.clear();
st.push_back({0, -1, {}});
occ.push_back(0);
tot.push_back(0);
last = 0;
}
void extend(int c) {
int cur = st.size();
st.push_back({st[last].len + 1, 0, {}});
occ.push_back(1);
tot.push_back(0);
int p = last;
while (p != -1 && !st[p].next.count(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 = st.size();
st.push_back(st[q]);
st[clone].len = st[p].len + 1;
tot.push_back(0);
occ.push_back(0);
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;
}
void build_occ() {
int sz = st.size();
vector<int> cnt_len(st[last].len + 1, 0);
for (auto &s : st) cnt_len[s.len]++;
for (int i = 1; i < (int)cnt_len.size(); i++)
cnt_len[i] += cnt_len[i - 1];
vector<int> order(sz);
for (int i = sz - 1; i >= 0; i--)
order[--cnt_len[st[i].len]] = i;
for (int i = sz - 1; i > 0; i--) {
int v = order[i];
int p = st[v].link;
if (p >= 0) occ[p] += occ[v];
}
}
void build_tot() {
int sz = st.size();
vector<int> outdeg(sz, 0);
vector<vector<int>> rev(sz);
for (int u = 0; u < sz; u++) {
for (auto &kv : st[u].next) {
int v = kv.second;
outdeg[u]++;
rev[v].push_back(u);
}
}
queue<int> q;
for (int i = 0; i < sz; i++)
if (outdeg[i] == 0) q.push(i);
while (!q.empty()) {
int u = q.front();
q.pop();
for (int p : rev[u]) {
tot[p] += occ[u] + tot[u];
if (--outdeg[p] == 0) q.push(p);
}
}
}
vector<int> kth_substring(ll K) {
vector<int> ans;
int u = 0;
while (K > 0) {
bool found = false;
for (auto &kv : st[u].next) {
int c = kv.first, v = kv.second;
// 子串 S = 前缀 + c,本身的出现次数
if (K <= occ[v]) {
ans.push_back(c);
return ans;
}
K -= occ[v];
// 更长的那些以 S 为前缀的子串
if (K <= tot[v]) {
ans.push_back(c);
u = v;
found = true;
break;
}
K -= tot[v];
}
if (!found) break;
}
return ans;
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--) {
int N;
ll K;
cin >> N >> K;
vector<int> A(N);
for (int i = 0; i < N; i++) {
cin >> A[i];
}
SuffixAutomaton sam(N);
for (int x : A) sam.extend(x);
sam.build_occ();
sam.build_tot();
auto res = sam.kth_substring(K);
for (int i = 0; i < (int)res.size(); i++) {
if (i) cout << ' ';
cout << res[i];
}
cout << "\n";
}
return 0;
}