#include <bits/stdc++.h>
using namespace std;
#define P pair
#define fi first
#define se second
#define eb emplace_back
#define vec vector
namespace lzyqwq {
const int N = 50005; P<int, int> arr[N];
int n, m, lg[N], ans[N], pmn[N]; string s; vec<int> buc;
struct SparseTable {
int a[20][N];
void build(int *b) {
for (int i = 1; i <= n; ++i) a[0][i] = b[i];
for (int i = 1; i <= lg[n]; ++i)
for (int j = 1; j + (1 << i) - 1 <= n; ++j)
a[i][j] = min(a[i - 1][j], a[i - 1][j + (1 << (i - 1))]);
}
int Q(int l, int r) {
int k = lg[r - l + 1]; return min(a[k][l], a[k][r - (1 << k) + 1]);
}
};
struct SuffixArray {
int sa[N], rk[N], ht[N], tmp[30]; P<P<int, int>, int> p[N]; SparseTable st;
void work() {
memset(tmp, 0, sizeof tmp);
for (int i = 1; i <= n; ++i) ++tmp[s[i] - 'a' + 1];
for (int i = 1; i <= 26; ++i) tmp[i] += tmp[i - 1];
for (int i = 1; i <= n; ++i) rk[i] = tmp[s[i] - 'a'] + 1;
for (int l = 1, id; l <= n; l <<= 1) {
for (int i = 1; i <= n; ++i)
p[i] = {{rk[i], i + l > n ? 0 : rk[i + l]}, i};
stable_sort(p + 1, p + n + 1); id = 0;
for (int i = 1; i <= n; ++i) {
if (i == 1 || p[i].fi != p[i - 1].fi) ++id; rk[p[i].se] = id;
}
if (id == n) break;
}
for (int i = 1; i <= n; ++i) sa[rk[i]] = i, ht[i] = 0;
for (int i = 1, j, k = 0; i <= n; ++i) {
if (rk[i] == 1) { k = 0; continue; }
if (k) --k; j = sa[rk[i] - 1];
while (i + k <= n && j + k <= n && s[i + k] == s[j + k]) ++k;
ht[rk[i]] = k;
}
st.build(ht);
}
int lcp(int x, int y) {
if (x == y) return n - sa[x] + 1;
if (x > y) swap(x, y); ++x; return st.Q(x, y);
}
} S;
struct ChairmanTree {
int ls[N * 20], rs[N * 20], cnt, sum[N * 20], rt[N];
void I() {
for (int i = 1; i <= cnt; ++i) ls[i] = rs[i] = sum[i] = 0;
for (int i = 1; i <= n; ++i) rt[i] = 0; cnt = 0;
}
void mdf(int &x, int y, int l, int r, int k, int v) {
x = ++cnt; sum[x] = sum[y] + v;
if (l == r) return; int m = (l + r) >> 1;
if (k <= m) rs[x] = rs[y], mdf(ls[x], ls[y], l, m, k, v);
else ls[x] = ls[y], mdf(rs[x], rs[y], m + 1, r, k, v);
}
int qry(int x, int y, int l, int r, int ql, int qr) {
if (ql <= l && r <= qr) return sum[x] - sum[y];
int m = (l + r) >> 1, R = 0;
if (ql <= m) R = qry(ls[x], ls[y], l, m, ql, qr);
if (qr > m) R += qry(rs[x], rs[y], m + 1, r, ql, qr); return R;
}
void M(int x, int y, int k, int v) { mdf(rt[x], rt[y], 1, n, k, v); }
int Q(int x, int y, int l, int r) {
if (x > y || l > r) return 0;
return qry(rt[y], rt[x - 1], 1, n, l, r);
}
} T;
struct Qries {
int l, r, k, id;
Qries(int ll = 0, int rr = 0, int kk = 0, int ii = 0) {
l = ll; r = rr; k = kk; id = ii;
}
}; vec<Qries> q[N];
void init() {
T.I(); for (int i = 1; i <= n; ++i) q[i].clear();
}
int count(int l, int r) {
return upper_bound(buc.begin(), buc.end(), r) -
lower_bound(buc.begin(), buc.end(), l);
}
void cdq(int l, int r) {
if (l == r) return; int m = (l + r) >> 1;
pmn[m + 1] = S.ht[m + 1]; T.I(); buc.clear();
for (int i = m + 2; i <= r; ++i) pmn[i] = min(S.ht[i], pmn[i - 1]);
for (int i = m + 1; i <= r; ++i)
buc.eb(S.sa[i]), arr[i] = {S.sa[i] + pmn[i], S.sa[i]};
stable_sort(arr + m + 1, arr + r + 1); stable_sort(buc.begin(), buc.end());
for (int i = m + 1; i <= r; ++i) T.M(i, i - 1, arr[i].se, 1);
for (int i = m, mn = N, ql, qr, f, mid; i >= l; --i) {
for (auto [L, R, k, id] : q[i]) {
ql = m + 1, qr = r, f = m, mid;
while (ql <= qr) {
int mid = (ql + qr) >> 1;
if (arr[mid].fi <= R) f = mid, ql = mid + 1; else qr = mid - 1;
}
ans[id] += count(max(R - mn, k) + 1, R) -
T.Q(m + 1, f, max(k, R - mn) + 1, R);
}
mn = min(mn, S.ht[i]);
}
cdq(l, m); cdq(m + 1, r);
}
void work() {
init(); cin >> n >> m >> s; s = ' ' + s; S.work();
for (int i = 1; i <= n; ++i) T.M(i, i - 1, S.sa[i], 1);
for (int i = 1, l, r, k; i <= m; ++i) {
cin >> l >> r >> k; q[S.rk[k]].eb(l, r, k, i); ans[i] = 0;
if (r != k) ans[i] = T.Q(1, S.rk[k] - 1, k + 1, r);
if (l != k) {
int ql = 1, qr = S.rk[k], f = 0, md;
while (ql <= qr) {
md = (ql + qr) >> 1;
if (S.lcp(md, S.rk[k]) <= r - k) f = md, ql = md + 1;
else qr = md - 1;
}
ans[i] += T.Q(1, f, l, k - 1);
}
}
cdq(1, n); for (int i = 1; i <= m; ++i) cout << ans[i] + 1 << '\n';
}
void Main() {
cin.tie(0), cout.tie(0), ios::sync_with_stdio(0);
for (int i = 1; i < N; ++i) lg[i] = __lg(i);
int testcases; cin >> testcases; while (testcases--) work();
}
}
signed main(void)
{
return lzyqwq::Main(), 0;
}
P9623 [ICPC2020 Nanjing R] Baby‘s First Suffix Array Problem
于 2024-09-16 19:27:45 首次发布