K-th occurrence

Posted czy-power

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n",p);
    
//    for (register int i = 1; i <= n; ++i) 
//        printf("sa[ %d ] = %d\n", 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\n", 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\n",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\n",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\n",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\n",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\n",ans_l,ans_r);
            if (ans_r - ans_l + 1 < k) 
                puts("-1");
             else 
                printf("%d\n", query(root[ans_l - 1], root[ans_r], 1, n, k));
            
        
    
    return 0;

 

 

以上是关于K-th occurrence的主要内容,如果未能解决你的问题,请参考以下文章

K-th Number

K-th Number

poj[2104]K-th Number

[POJ 2104]K-th Number

[POJ 2104]K-th Number

poj2104K-th Number