后缀数组SA与LCP

#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
const i64 mod = 998244353;

const int N = 2e6 + 5;
const int M = 1e6 + 5;
int sa[N + 1], rk[N + 1], y[N + 1], cnt[M + 1], h[N + 1], mn[N + 1][21], lg[N + 1];
void SA(string s) {
    int n = s.size(), m = 300;
    s = "$" + s;
    for (int i = 1; i <= n; i++) cnt[rk[i] = s[i]]++;
    for (int i = 1; i <= m; i++) cnt[i] += cnt[i - 1];
    for (int i = n; i >= 1; i--) sa[cnt[rk[i]]--] = i;
    for (int k = 1; k <= n; k <<= 1) {
        memset(cnt, 0, sizeof cnt);
        for (int i = 1; i <= n; i++) y[i] = sa[i];
        for (int i = 1; i <= n; i++) cnt[rk[y[i] + k]]++;
        for (int i = 1; i <= m; i++) cnt[i] += cnt[i - 1];
        for (int i = n; i; i--) sa[cnt[rk[y[i] + k]]--] = y[i];
        memset(cnt, 0, sizeof cnt);
        for (int i = 1; i <= n; i++) y[i] = sa[i];
        for (int i = 1; i <= n; i++) cnt[rk[y[i]]]++;
        for (int i = 1; i <= m; i++) cnt[i] += cnt[i - 1];
        for (int i = n; i; i--) sa[cnt[rk[y[i]]]--] = y[i];
        m = 0;
        for (int i = 1; i <= n; i++) y[i] = rk[i];
        for (int i = 1; i <= n; i++) {
            if (i == 1 || y[sa[i]] != y[sa[i - 1]] || y[sa[i] + k] != y[sa[i - 1] + k]) {
                ++m;
            }
            rk[sa[i]] = m;
        }
        if (m == n) return;
    }
}

void height(string s) {
    int n = s.size();
    s = "$" + s;
    for (int i = 1, k = 0; i <= n; i++) {
        k = max(k - 1, 0);
        if (rk[i] == 1) continue;
        int j = sa[rk[i] - 1];
        while (i + k <= n && j + k <= n && s[i + k] == s[j + k]) k++;
        h[rk[i]] = k;
    }
    for (int i = 2; i <= n; i++) lg[i] = lg[i >> 1] + 1;
    for (int i = 1; i <= n; i++) mn[i][0] = h[i];
    for (int i = 1; i <= 20; i++) {
        for (int j = 1; j + (1 << i) - 1 <= n; j++) {
            mn[j][i] = min(mn[j][i - 1], mn[j + (1 << i - 1)][i - 1]);
        }
    }
}

int lcp(int x, int y, int n) {
    if (x == y) return n - x + 1;
    if (rk[x] > rk[y]) swap(x, y);
    int k = lg[rk[y] - rk[x]];
    return min(mn[rk[x] + 1][k], mn[rk[y] - (1 << k) + 1][k]);
}

void solve() {
    int n; cin >> n;
    string s; cin >> s;
    SA(s); height(s);
    int m = s.size();
    for (int i = 1; i <= n; i++) {
        int l1, r1, l2, r2; cin >> l1 >> r1 >> l2 >> r2;
        int sum = min({r1 - l1 + 1, r2 - l2 + 1, lcp(l1, l2, m)});
        cout << sum << '\n';
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int _ = 1;
    // cin >> _;
    while (_--) {
        solve();
    }
    return 0;
}

posted @ 2025-06-13 23:57  grape_king  阅读(7)  评论(0)    收藏  举报