【比赛链接】
【题解链接】
【C】K-th Substring
【思路要点】
- 注意到\(K\)很小,我们考虑每次找到该字符串最小的子串,并在后续的过程中不再考虑该子串。
- 对于以\(i\)号字符开头的子串\(S_{i,i}\),\(S_{i,i+1}\),\(S_{i,i+2}\)……,显然有\(S_{i,i}<S_{i,i+1},S_{i,i+2}<……\)。
- 因此,在每一轮中,我们只需要考虑以每个位置开头的,尚未被找到过的最短的子串。
- 在这些子串中暴力找到字典序最小的即可。
- 时间复杂度\(O(min\{K^2N,KN^2\})\)。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 100005; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } char s[MAXN]; int n, k, now[MAXN]; bool better(int a, int lena, int b, int lenb) { if (lena == -1) return false; if (lenb == -1) return true; int len = min(lena, lenb); for (int i = 1; i <= len; i++) { if (s[a + i - 1] < s[b + i - 1]) return true; if (s[a + i - 1] > s[b + i - 1]) return false; } return lena < lenb; } bool equal(int a, int b, int len) { for (int i = 1; i