[2019CCPC network race] [hdu6704] K-th occurrence (Chairman & tree suffix array)

Topic links: http://acm.hdu.edu.cn/showproblem.php?pid=6704

Title means query substring s [l ... r] k-th position appears.

5 minutes after finish blog update


Written blog found this code and electrical code check Hang heavy ....

Why would this be it? Is my first post, it was my first post ...


excitement! ! The first network to make this race (the board) title.

First, ask about Height suffix array, we know Height array represents the longest common prefix of suffix of two adjacent rankings, the interval is the minimum value of the Height of the array adjacent sections ranking suffix longest common prefix.

Height We want to know who suffix array contains the query interval s [l ... r] such a prefix, first find the s [l ... n] suffix ranking, then include this ranking is found in the most long interval, and a minimum value of the interval greater than or equal to r-l + 1. I.e., the longest common prefixes and suffixes in the interval contains s [l ... r].

Looking for the longest interval can be approximately half of each endpoint is determined by pre-Height array table ST, and O (1) query.

Then our task is to find a small position of k in this range. This problem can be built Chairman of the tree of rank suffix array. Then query.

#include<bits/stdc++.h>
#define lson l,mid,i<<1
#define rson mid+1,r,i<<1|1
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 2e5 + 110;
int sa[maxn], tax[maxn], rak[maxn], tp[maxn], Height[maxn], lg[maxn];
int dp[maxn][20];
int root[maxn], ls[maxn * 40], rs[maxn * 40], val[maxn * 40], cnt;
char s[maxn];
void Qsort(int n, int m) {
    for (int i = 0; i < m; i++) tax[i] = 0;
    for (int i = 0; i < n; i++) tax[rak[i]]++;
    for (int i = 0; i < m; i++) tax[i] += tax[i - 1];
    for (int i = n - 1; i >= 0; i--) sa[--tax[rak[tp[i]]]] = tp[i];
}
void suffix(int n, int m) {//n为原串长度+1,m为原串的种类
    for (int i = 0; i < n; i++)
        rak[i] = s[i], tp[i] = i;
    Qsort(n, m);
    //debug();
    for (int k = 1; k <= n; k <<= 1) {
        int p = 0;
        for (int i = n - k; i < n; i++) tp[p++] = i;
        for (int i = 0; i < n; i++) if (sa[i] >= k) tp[p++] = sa[i] - k;
        Qsort(n, m);
        swap(rak, tp);
        p = 1;
        rak[sa[0]] = 0;
        for (int i = 1; i < n; i++)
            rak[sa[i]] = (tp[sa[i - 1]] == tp[sa[i]] && tp[sa[i - 1] + k] == tp[sa[i] + k]) ? p - 1 : p++;
        if (p >= n)
            break;
        m = p;
    }
}
void getH(int n) {
    int j, k = 0;
    for (int i = 0; i <= n; i++)
        rak[sa[i]] = i;
    for (int i = 0; i < n; i++) {
        if (k)k--;
        j = sa[rak[i] - 1];
        while (s[i + k] == s[j + k])
            k++;
        Height[rak[i]] = k;
    }
}
void RMQ(int n) {
    for (int i = 1; i <= n; i++)
        dp[i][0] = Height[i];
    for (int j = 1; (1 << j) <= n; j++) {
        for (int i = 1; i + (1 << j) - 1 <= n; i++)
            dp[i][j] = min(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
    }
    lg[0] = -1;
    for (int i = 1; i <= n; i++) {
        if ((i&(i - 1)) == 0)
            lg[i] = lg[i - 1] + 1;
        else
            lg[i] = lg[i - 1];
    }
}
int queryR(int l, int r) {
    int k = lg[r - l + 1];
    return min(dp[l][k], dp[r - (1 << k) + 1][k]);
}
void build(int l, int r, int &i) {
    i = ++cnt;
    val[i] = 0;
    if (l == r)
        return;
    int mid = l + r >> 1;
    build(l, mid, ls[i]);
    build(mid + 1, r, rs[i]);
}
void update(int k, int l, int r, int &i) {
    ls[++cnt] = ls[i], rs[cnt] = rs[i], val[cnt] = val[i] + 1;
    i = cnt;
    if (l == r)
        return;
    int mid = l + r >> 1;
    if (k <= mid)
        update(k, l, mid, ls[i]);
    else
        update(k, mid + 1, r, rs[i]);
}
int query(int u, int v, int k, int l, int r) {
    if (l == r)
        return l;
    int x = val[ls[v]] - val[ls[u]];
    int mid = l + r >> 1;
    if (x >= k)
        return query(ls[u], ls[v], k, l, mid);
    else
        return query(rs[u], rs[v], k - x, mid + 1, r);
}
int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        int n, q, cnt = 0;
        scanf("%d%d", &n, &q);
        scanf("%s", s);
        suffix(n + 1, 256);
        getH(n);
        for (int i = 1; i <= n; i++)
            ++sa[i];
        for (int i = n; i >= 1; i--)
            rak[i] = rak[i - 1];
        RMQ(n);
        build(1, n, root[0]);
        for (int i = 1; i <= n; i++) {
            root[i] = root[i - 1];
            update(sa[i], 1, n, root[i]);
        }
        //
         L = x + 1, R = n;
            while (L <= R) {
                int mid = L + R >> 1;
                if (queryR(L, mid) >= len)
                    y = mid, L = mid + 1;
                else
                    R = mid - 1;
            }
            L = 2, R = x;
            while (L <= R) {
                int mid = L + R >> 1;
                if (queryR(mid, R) >= len)
                    x = mid - 1, R = mid - 1;
                else
                    L = mid + 1;
            }
            //cout << x << " " << y << endl;
            if (y - x + 1 < k)
                printf("-1\n");
            else
                printf("%d\n", query(root[x - 1], root[y], k, 1, n));
        }
    }
}

 

Guess you like

Origin www.cnblogs.com/sainsist/p/11409152.html