[2019ccpc网络赛】K-th occurrence(后缀数组+主席树)

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
 

 

Source
 

 

Recommend
liuyiding   |   We have carefully selected several similar problems for you:  6724 6723 6722 6721 6720 
 
 
SOLUTION:
 
算板子吧,很好理解
 
CODE:
#include<bits/stdc++.h>
using namespace std;

int n,q;
const int N = 3e5+10;

char  s[N];
int sa[N],c[N];
int t1[N],t2[N];
int height[N];
int r[N];
int RMQ[N];
int mm[N];
int best[50][N];
int Rank[N];



void da(int m  )
{
    int i,*x=t1,*y=t2;
    for(i = 1; i <= m; i++) c[i] = 0;
    for(i = 1; i <= n; i++) c[x[i] = s[i]]++;
    for(i = 1; i <= m; i++) c[i] += c[i - 1];
    for(i = n; i >= 1; i--) sa[c[x[i]]--] = i;
    for(int k = 1; k <= n; k <<= 1)
    {
        int p = 0;
        for(i = n - k + 1; i <= n; i++) y[++p] = i;
        for(i = 1; i <= n; i++) if(sa[i] > k) y[++p] = sa[i] - k;
        for(i = 1; i <= m; i++) c[i] = 0;
        for(i = 1; i <= n; i++) c[x[y[i]]]++;
        for(i = 1; i <= m; i++) c[i] += c[i - 1];
        for(i = n; i >= 1; i--) sa[c[x[y[i]]]--] = y[i];
        swap(x, y);
        p = 1;
        x[sa[1]] = 1;
        for(i = 2; i <= n; i++)
            x[sa[i]] = (y[sa[i]] == y[sa[i - 1]]
                        && y[sa[i] + k] == y[sa[i - 1] + k]) ?
                       p : ++p;
        if(p >= n) break;
        m = p;
    }
}
void getheight()
{
    int i, j, k = 0;
    for(i = 1; i <= n; i++) Rank[sa[i]] = i;
    for(i = 1; i <= n; i++)
    {
        if(k) k--;
        j=sa[Rank[i] - 1];
        while(s[j+k] == s[i+k]) k++;
        height[Rank[i]] = k;
    }
}


void initrmq(int n)
{
    mm[0]=-1;
    for(int i=1; i<=n; i++)
        mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];

    for(int i=1; i<=n; i++)best[0][i]=i;

    for(int i=1; i<=25; i++)
    {
        for(int j=1; j+(1<<i)-1<=n; j++)
        {
            int a=best[i-1][j];
            int b=best[i-1][j+(1<<(i-1))];
            if(RMQ[a]<RMQ[b])best[i][j]=a;
            else best[i][j]=b;
        }
    }
}
int askRMQ(int a,int b)
{
    int t;
    t=mm[b-a+1];
    b-=(1<<t)-1;
    a=best[t][a];
    b=best[t][b];
    return RMQ[a]<RMQ[b]?a:b;
}
int lcp(int a,int b)
{
    a=Rank[a],b=Rank[b];
    if(a>b)swap(a,b);
    return height[askRMQ(a+1,b)];
}

int tr[N*70],tot,root[N];
int ls[N*70],rs[N*70];

void cha(int y,int &x,int l,int r,int p)
{
    x=++tot;
    tr[x]=tr[y]+1;
    ls[x]=ls[y],rs[x]=rs[y];
    if(l==r)return ;
    int mid=l+r>>1;
    if(p<=mid)cha(ls[y],ls[x],l,mid,p);
    else cha(rs[y],rs[x],mid+1,r,p);
}

int que(int y,int x,int l,int r,int k)
{
    if(l==r)return l;
    int mid=l+r>>1;
    int sum=tr[ls[x]]-tr[ls[y]];
    if(k<=sum)return que(ls[y],ls[x],l,mid,k);
    else return que(rs[y],rs[x],mid+1,r,k-sum);
}

void Build()
{
    tot=0;
    memset(tr,0,sizeof tr);
    memset(root,0,sizeof root);
    memset(ls,0,sizeof ls);
    memset(rs,0,sizeof rs);

    for(int i=1; i<=n; i++)
        cha(root[i-1],root[i],1,n,sa[i]);

}

signed main()
{
    int T;
    cin>>T;
#define sc(x) scanf("%d",&(x))
    while(T--)
   {
        sc(n);
        sc(q);
        memset(s,0,sizeof s);
        scanf("%s",s+1);
        int len=strlen(s+1);
        da(250);
        getheight();
        memset(RMQ,0,sizeof RMQ);
        for(int i=1; i<=n; i++)RMQ[i]=height[i];
        initrmq(n);
        Build();
        while(q--)
        {
            int l,r,k;
            sc(l);sc(r);sc(k);
            int len=r-l+1;
            int up=-1,down=-1;
            int L,R;

            R=Rank[l]-1;
            L=1;
            up=Rank[l];

            while(L<=R)
            {
                int mid=L+R>>1;
                if(lcp(sa[mid],sa[Rank[l]])<len)
                {
                    L=mid+1;
                }
                else
                {
                    R=mid-1;
                    up=mid;
                }
            }

            L=Rank[l]+1;
            R=n;
            down=Rank[l];
            while(L<=R)
            {
                int mid=L+R>>1;
                if(lcp(sa[mid],sa[Rank[l]])<len)
                {
                    R=mid-1;
                }
                else
                {
                    L=mid+1;
                    down=mid;
                }
            }

            int x=root[up-1];
            int y=root[down];

            if(tr[y]-tr[x]<k || down<up)
            {
                puts("-1");continue;
            }
            int ans=que(x,y,1,n,k);
            cout<<ans<<endl;
        }

    }
}

  

 
原文地址:https://www.cnblogs.com/zhangbuang/p/11420878.html