zoukankan      html  css  js  c++  java
  • 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.
     
    Input
    The first line contains an integer T(1T20), denoting the number of test cases.

    The first line of each test case contains two integer N(1N105),Q(1Q105), 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(1lrN) and k(1kN), 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.
     
    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
    ",p);
        }
    //    for (register int i = 1; i <= n; ++i) {
    //        printf("sa[ %d ] = %d
    ", 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
    ", 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
    ",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
    ",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
    ",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
    ",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
    ",ans_l,ans_r);
                if (ans_r - ans_l + 1 < k) {
                    puts("-1");
                } else {
                    printf("%d
    ", query(root[ans_l - 1], root[ans_r], 1, n, k));
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    Educational Codeforces Round 33 (Rated for Div. 2) B. Beautiful Divisors【进制思维/打表】
    Educational Codeforces Round 33 (Rated for Div. 2) A. Chess For Three【模拟/逻辑推理】
    java中的BigInteger
    动态规划-最长上升子序列(LIS模板)多解+变形
    Rain on your Parade---hdu2389(HK求最大匹配)
    Air Raid---hdu1151(最小路径覆盖)
    Swap---hdu2819(最大匹配)
    棋盘游戏---hdu1281(最大匹配)
    The Accomodation of Students---hdu2444(二分图,最大匹配)
    COURSES---poj1469 hdu1083(最大匹配)
  • 原文地址:https://www.cnblogs.com/czy-power/p/11404138.html
Copyright © 2011-2022 走看看