You are given a string S consisting of only lowercase english letters and some queries.c++
For each query (l,r,k), please output the starting position of the k-th occurence of the substring $S_lS_{l+1}...S_r $in S.數組
The first line contains an integer T(1≤T≤20), denoting the number of test cases.ui
The first line of each test case contains two integer N(1≤N≤\(10^5\)),Q(1≤Q≤\(10^5\)), denoting the length of S and the number of queries.spa
The second line of each test case contains a string S(|S|=N) consisting of only lowercase english letters.code
Then Q lines follow, each line contains three integer l,r(1≤l≤r≤N) and k(1≤k≤N), denoting a query.three
There are at most 5 testcases which N is greater than \(10^3\).ip
For each query, output the starting position of the k-th occurence of the given substring.字符串
If such position don't exists, output −1 instead.get
2 12 6 aaabaabaaaab 3 3 4 2 3 2 7 8 3 3 4 2 1 4 2 8 12 1 1 1 a 1 1 1
5 2 -1 6 9 8 1
給定一個字符串,每次詢問[l,r]的字符串第k次出現的位置,沒有則輸出-1input
後綴數組理解深入的話應該能夠秒掉這道題
首先,height[i]表示排名第i位的和第i-1位的最長公共前綴,因此咱們要找某個子串出現的全部位置,只須要在height數組中二分,詢問的字串所處後綴的排名即爲\(rk[l]\),那麼咱們從\(rk[l]\)開始向上向下二分,讓這段的區間height最小值大於r-l+1,那麼他們就都有r-l+1的最長公共前綴,咱們找出這個邊界後,用主席樹求這個區間中sa數組的第k大便可。
#include <bits/stdc++.h> using namespace std; const int N = 1e5 + 10; typedef long long ll; char s[N]; int x[N], y[N], c[N], sa[N], rk[N], height[N]; int n, m, q; void tsort() { for (int i = 0; i <= m; i++) c[i] = 0; for (int i = 1; i <= n; i++) c[x[i]]++; for (int i = 2; i <= m; i++) c[i] += c[i - 1]; for (int i = n; i >= 1; i--) sa[c[x[y[i]]]--] = y[i]; } void get_sa() { memset(c, 0, sizeof(c)); memset(x, 0, sizeof(x)); memset(y, 0, sizeof(y)); for (int i = 1; i <= n; i++) x[i] = s[i], y[i] = i; tsort(); for (int k = 1; k <= n; k <<= 1) { int num = 0; for (int i = n - k + 1; i <= n; i++) y[++num] = i; for (int i = 1; i <= n; i++) if (sa[i] > k) y[++num] = sa[i] - k; tsort(); swap(x, y); x[sa[1]] = 1; num = 1; for (int i = 2; i <= n; i++) x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k]) ? num : ++num; if (num == n) break; m = num; } } void get_h() { int k = 0; for (int i = 1; i <= n; i++) rk[sa[i]] = i; for (int i = 1; i <= n; i++) { if (rk[i] == 1) continue; if (k) k--; int j = sa[rk[i] - 1]; while (s[i + k] == s[j + k]) k++; height[rk[i]] = k; } } int st[N][20], lg2[N]; void ST() { for (int i = 1; i <= n; i++) { st[i][0] = height[i]; } for (int j = 1; (1 << j) <= n; j++) { for (int i = 1; (i + (1 << j) - 1) <= n; i++) { st[i][j] = min(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]); } } for (int i = 2; i <= n; i++) { lg2[i] = lg2[i >> 1] + 1; } } int rmq(int l, int r) { if (l > r) return 0; else { int x = lg2[r - l + 1]; return min(st[l][x], st[r - (1 << x) + 1][x]); } } int L[N * 40], R[N * 40], T[N], cnt; ll sum[N * 40]; int build(int l, int r) { int rt = ++cnt; sum[rt] = 0; int mid = (l + r) >> 1; if (l < r) { L[rt] = build(l, mid); R[rt] = build(mid + 1, r); } return rt; } int update(int pre, int l, int r, int x) { int rt = ++cnt; int mid = (l + r) >> 1; L[rt] = L[pre], R[rt] = R[pre], sum[rt] = sum[pre] + 1; if (l < r) { if (x <= mid) L[rt] = update(L[pre], l, mid, x); else R[rt] = update(R[pre], mid + 1, r, x); } return rt; } int query(int u, int v, int l, int r, int k) { if (l >= r) { return l; } int mid = (l + r) >> 1; int x = sum[L[v]] - sum[L[u]]; if (x >= k) return query(L[u], L[v], l, mid, k); else { if (sum[R[v]] - sum[R[u]] < k - x) return -1; return query(R[u], R[v], mid + 1, r, k - x); } } int main() { int t; scanf("%d", &t); while (t--) { m = 130; scanf("%d%d", &n, &q); scanf("%s", s + 1); cnt = 0; get_sa(); get_h(); ST(); T[0] = build(1, n); for (int i = 1; i <= n; i++) { T[i] = update(T[i - 1], 1, n, sa[i]); } while (q--) { int l, r, k; scanf("%d%d%d", &l, &r, &k); int tl = rk[l], tr = rk[l]; int x = 1, y = rk[l]; while (x <= y) { int mid = (x + y) >> 1; if (rmq(mid, rk[l]) >= r - l + 1) { y = mid - 1; tl = min(tl, mid - 1);//注意細節 } else x = mid + 1; } x = rk[l] + 1, y = n;//注意細節 while (x <= y) { int mid = (x + y) >> 1; if (rmq(rk[l] + 1, mid) >= r - l + 1) { x = mid + 1; tr = max(tr, mid); } else y = mid - 1; } printf("%d\n", query(T[tl - 1], T[tr], 1, n, k)); } } return 0; }