全WA求调SA+主席树+二分!帮帮孩子吧!要看疯了!
查看原帖
全WA求调SA+主席树+二分!帮帮孩子吧!要看疯了!
1343921
Luxizhel楼主2024/4/18 22:49

rt,调了一整天了,愣是没看出来一个问题,除了hack数据外全WA,求大佬帮看看,一定关注!谢谢!

ps:二分写的是左闭右闭的版本(也可以理解为左开右开?)

#include <algorithm>
#include <cstring>
#include <iostream>
#define lc(x) tr[x].left_son
#define rc(x) tr[x].right_son

using namespace std;

const int N = 2e5 + 5;

int n, m, sa[N], rk[N], ork[N], h[N], lg[N], st[N][18];
char s[N];
int root[N], idx; // 主席树
struct
{
    int l, r, left_son, right_son, sum;
} tr[20 * N];

void build(int u, int l, int r)
{
    tr[u] = {l, r};
    if (l == r)
        return;
    int mid = l + r >> 1;
    build(lc(u) = ++idx, l, mid), build(rc(u) = ++idx, mid + 1, r);
}

void modify(int prv, int u, int p)
{
    tr[u] = tr[prv], tr[u].sum++;
    if (tr[u].l == tr[u].r)
        return;
    int mid = tr[u].l + tr[u].r >> 1;
    if (p <= mid)
        modify(lc(prv), lc(u) = ++idx, p);
    else
        modify(rc(prv), rc(u) = ++idx, p);
}

int query(int prv, int u, int l, int r)
{
    if (tr[u].l >= l && tr[u].r <= r)
        return tr[u].sum - tr[prv].sum;
    int mid = tr[u].l + tr[u].r >> 1, sum = 0;
    if (l <= mid)
        sum = query(lc(prv), lc(u), l, r);
    if (r > mid)
        sum += query(rc(prv), rc(u), l, r);
    return sum;
}

void sfx_ary()
{
    for (int i = 1; i <= n; i++)
        sa[i] = i, rk[i] = s[i];
    for (int w = 1, r = 0; r < n; w <<= 1) // nlog^2n SA
    {
        sort(sa + 1, sa + n + 1, [w](int x, int y) { return rk[x] != rk[y] ? rk[x] < rk[y] : rk[x + w] < rk[y + w]; });
        memcpy(ork, rk, sizeof rk), r = 0;
        for (int i = 1; i <= n; i++)
        {
            if (ork[sa[i]] != ork[sa[i - 1]] || ork[sa[i] + w] != ork[sa[i - 1] + w])
                r++;
            rk[sa[i]] = r;
        }
    }
    for (int i = 1, k = 0; i <= n; i++) // 求 height
    {
        if (rk[i] == 1)
            continue;
        if (k)
            k--;
        while (s[i + k] == s[sa[rk[i] - 1] + k])
            k++;
        h[rk[i]] = k;
    }
    lg[0] = -1;
    for (int i = 1; i <= n; i++) // rmq
        st[i][0] = h[i], lg[i] = lg[i >> 1] + 1;
    for (int i = 1; 1 << i <= n; i++)
        for (int j = 1; j + (1 << i) - 1 <= n; j++)
            st[j][i] = min(st[j][i - 1], st[j + (1 << i - 1)][i - 1]);
    root[0] = ++idx, build(root[0], 1, n);
    for (int i = 1; i <= n; i++)
        root[i] = ++idx, modify(root[i - 1], root[i], sa[i]);
}

int gmin(int l, int r)
{
    int len = lg[r - l + 1];
    return min(st[l][len], st[r - (1 << len) + 1][len]);
}

bool check(int sl, int sr, int pos, int val)
{
    int lp, rp, l = 0, r = sa[pos];
    while (l + 1 < r)
    {
        int mid = l + r >> 1;
        (gmin(mid + 1, sa[pos]) >= val ? r : l) = mid;
    }
    lp = r, l = sa[pos], r = n + 1;
    while (l + 1 < r)
    {
        int mid = l + r >> 1;
        (gmin(sa[pos] + 1, mid) >= val ? l : r) = mid;
    }
    rp = l;
    return query(root[lp - 1], root[rp], sl, sr);
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0);
    cin >> n >> m >> s + 1;
    sfx_ary();
    while (m--)
    {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        int l = 0, r = min(b - a, d - c) + 2;
        while (l + 1 < r)
        {
            int mid = l + r >> 1;
            (check(a, b - mid + 1, c, mid) ? l : r) = mid;
        }
        cout << l << "\n";
    }
    return 0;
}
2024/4/18 22:49
加载中...