K-th occurrence
K-th occurrence
Time Limit: 5000/5000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 461 Accepted Submission(s): 125
Problem Description
You are given a string S consisting of only lowercase english letters and some queries.
For each query (l,r,k), please output the starting position of the k-th occurence of the substring SlSl+1...Sr in S.
For each query (l,r,k), please output the starting position of the k-th occurence of the substring SlSl+1...Sr in S.
Input
The first line contains an integer T(1≤T≤20), denoting the number of test cases.
The first line of each test case contains two integer N(1≤N≤105),Q(1≤Q≤105), denoting the length of S and the number of queries.
The second line of each test case contains a string S(|S|=N) consisting of only lowercase english letters.
Then Q lines follow, each line contains three integer l,r(1≤l≤r≤N) and k(1≤k≤N), denoting a query.
There are at most 5 testcases which N is greater than 103.
The first line of each test case contains two integer N(1≤N≤105),Q(1≤Q≤105), denoting the length of S and the number of queries.
The second line of each test case contains a string S(|S|=N) consisting of only lowercase english letters.
Then Q lines follow, each line contains three integer l,r(1≤l≤r≤N) and k(1≤k≤N), denoting a query.
There are at most 5 testcases which N is greater than 103.
Output
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.
If such position don't exists, output −1 instead.
Sample Input
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
Sample Output
5 2 -1 6 9 8 1
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = (1e5 + 10) * 100; int M = 30; int T, n, q, len, tot; char s[maxn]; int sa[maxn], height[maxn]; int rk[maxn], tp[maxn]; int str[maxn], ton[maxn], root[maxn]; int f[300600][36]; struct tree { int l, r, val; } c[maxn]; inline void rsort() { for (register int i = 0; i <= M; ++i)ton[i] = 0; for (register int i = 1; i <= len; ++i)ton[rk[i]]++; for (register int i = 1; i <= M; ++i)ton[i] = ton[i] + ton[i - 1]; for (register int i = len; i >= 1; --i)sa[ton[rk[tp[i]]]--] = tp[i]; } inline void get_height() { len++; for (register int i = 1; i <= len; ++i)rk[i] = str[i], tp[i] = i; rsort(); for (register int w = 1, p = 0; p < len && w <= len; M = p, w *= 2) { p = 0; for (register int i = len - w + 1; i <= len; ++i)tp[++p] = i; for (register int i = 1; i <= len; ++i) { if (sa[i] > w) { tp[++p] = sa[i] - w; } } rsort(); swap(rk, tp); rk[sa[1]] = p = 1; for (register int i = 2; i <= len; ++i) { rk[sa[i]] = (tp[sa[i - 1]] == tp[sa[i]] && tp[sa[i - 1] + w] == tp[sa[i] + w]) ? p : ++p; } if (p >= len)break; //printf("%d\n",p); } // for (register int i = 1; i <= n; ++i) { // printf("sa[ %d ] = %d\n", i, sa[i]); // } int cur_len = len; cur_len--; int k = 0; for (register int i = 1; i <= len; ++i)rk[sa[i]] = i; // for(register int i=1;i<=len;++i){ // printf("rk[ %d ] = %d\n", i, rk[i]); // } for (register int i = 1; i <= cur_len; ++i) { if (k)--k; else k = 0; int j = sa[rk[i] - 1]; while (str[i + k] == str[j + k])k++; height[rk[i]] = k; } } inline void init() { for (register int i = 1; i <= len; ++i)f[i][0] = height[i]; for (register int j = 1; j <= 23; ++j) { for (register int i = 1; i + (1 << j) - 1 <= len; ++i) { f[i][j] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]); } } } inline int query(int l, int r) { int cur = log2(r - l + 1.0); return min(f[l][cur], f[r - (1 << cur) + 1][cur]); } inline int update(int pre, int l, int r, int pos) { int nx = ++tot; c[nx] = c[pre]; c[nx].val++; if (l == r)return nx; int mid = l + r >> 1; if (pos <= mid) { c[nx].l = update(c[pre].l, l, mid, pos); } else { c[nx].r = update(c[pre].r, mid + 1, r, pos); } return nx; } inline int query(int pl, int pr, int l, int r, int val) { if (l == r)return l; int mid = l + r >> 1; if (c[c[pr].l].val - c[c[pl].l].val >= val) { return query(c[pl].l, c[pr].l, l, mid, val); } else { return query(c[pl].r, c[pr].r, mid + 1, r, val - (c[c[pr].l].val - c[c[pl].l].val)); } } int main() { //freopen("1.txt", "r", stdin); scanf("%d", &T); while (T--) { tot = 0; scanf("%d%d", &n, &q); scanf("%s", s + 1); len = strlen(s + 1); for (register int i = 0; i <= len + 1; ++i)root[i] = 0; M = 30; //printf("debug len = %d\n",len); for (register int i = 1; i <= len; ++i)str[i] = s[i] - 'a' + 1; str[len + 1] = 0; get_height(); init(); for (register int i = 1; i <= len + 1; ++i) { root[i] = update(root[i - 1], 1, n, sa[i]); //printf("debug root[%d] = %d\n",i,root[i]); } int l, r, k; while (q--) { scanf("%d%d%d", &l, &r, &k); int siz = r - l + 1; //printf("debug rk[l] = %d\n",rk[l]); l = rk[l]; int L = 1, R = l, ans_l, ans_r; while (L <= R) { int mid = L + R >> 1, cur; cur = 100000; if (mid + 1 <= l) cur = query(mid + 1, l); if (cur >= siz) { ans_l = mid; R = mid - 1; } else { L = mid + 1; } // cur = query(mid, l); // if (cur >= siz) { // ans_l = mid; // R = mid - 1; // } else { // L = mid + 1; // } } //printf("debug ans_l = %d\n",ans_l); L = l, R = len; while (L <= R) { int mid = L + R >> 1, cur; cur = 100000; if (l + 1 <= mid) cur = query(l + 1, mid); if (cur >= siz) { ans_r = mid; L = mid + 1; } else { R = mid - 1; } // cur = query(l, mid); // if (cur >= siz) { // ans_l = mid; // R = mid - 1; // } else { // L = mid + 1; // } } // int pos = rk[l - 1]; // int L = 1, R = pos, LL = pos, RR = pos; // while (L < R) { // int mid = (L + R) / 2; // if (query(mid, pos) >= r - l + 1) // R = mid; // else // L = mid + 1; // } // if (query(L, pos) >= r - l + 1) // LL = L - 1; // if (pos < n - 1) { // pos++; // L = pos, R = n - 1; // while (L < R) { // int mid = (L + R) / 2; // if (query(pos, mid) >= r - l + 1) // L = mid + 1; // else // R = mid; // } // if (query(pos, L) < r - l + 1) // L--; // if (L >= pos && query(pos, L) >= r - l + 1) // RR = L; // } //printf("debug ans_l = %d ans_r = %d\n",ans_l,ans_r); if (ans_r - ans_l + 1 < k) { puts("-1"); } else { printf("%d\n", query(root[ans_l - 1], root[ans_r], 1, n, k)); } } } return 0; }