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;
    }
  • 相关阅读:
    [ERR] Node 10.211.55.8:7001 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
    PAT A1137 Final Grading (25 分)——排序
    PAT A1136 A Delayed Palindrome (20 分)——回文,大整数
    PAT A1134 Vertex Cover (25 分)——图遍历
    PAT A1133 Splitting A Linked List (25 分)——链表
    PAT A1132 Cut Integer (20 分)——数学题
    PAT A1130 Infix Expression (25 分)——中序遍历
    PAT A1142 Maximal Clique (25 分)——图
    PAT A1141 PAT Ranking of Institutions (25 分)——排序,结构体初始化
    PAT A1140 Look-and-say Sequence (20 分)——数学题
  • 原文地址:https://www.cnblogs.com/czy-power/p/11404138.html
Copyright © 2011-2022 走看看