zoukankan      html  css  js  c++  java
  • hdu 6704 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

    思路:

    我们要找l~r的字串的兄弟串不难想到求lcp 通过二分我们可以找到最右和最左的排名 然后我们只要用可持久线段树维护下标  然后求下标第k小的字符串即可

    #include <bits/stdc++.h>
    using namespace std;
    const double pi = acos(-1.0);
    const int N = 1e5+1000;
    const int inf = 0x3f3f3f3f;
    const double eps = 1e-6;
    typedef long long ll;
    const ll mod = 1e9+7;
    int rt[N];
    struct tree{
        int l,r,v,ls,rs;
    }t[N<<5];
    int nico;
    void build(int &p,int l,int r){
        p=++nico;
        t[p].l=l; t[p].r=r;
        if(l==r){
            return ;
        }
        int mid=(l+r)>>1;
        build(t[p].ls,l,mid);
        build(t[p].rs,mid+1,r);
    }
    void update(int &p,int last,int x){
        p=++nico;
        t[p]=t[last];
        t[p].v++;
        if(t[p].l==t[p].r&&t[p].l==x){
            t[p].v=1;
            return ;
        }
        int mid=(t[p].l+t[p].r)>>1;
        if(x<=mid) update(t[p].ls,t[last].ls,x);
        else update(t[p].rs,t[last].rs,x);
    }
    int query(int p,int last,int k){
        if(t[p].l==t[p].r){
            return t[p].l;
        }
        int tmp=t[t[p].ls].v-t[t[last].ls].v;
        int mid=(t[p].l+t[p].r)>>1;
        if(tmp>=k) return query(t[p].ls,t[last].ls,k);
        else return query(t[p].rs,t[last].rs,k-tmp);
    }
    struct S_array{
        int s[N],sa[N],t[N],t2[N],c[N],n;
        int f[N][20];
        void build_sa(int m){
            int i,*x=t,*y=t2;
            for(i=0;i<m;i++)c[i]=0;
            for(i=0;i<n;i++)c[x[i]=s[i]]++;
            for(i=1;i<m;i++)c[i]+=c[i-1];
            for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
            for(int k=1;k<=n;k<<=1){
                int p=0;
                for(i=n-k;i<n;i++)y[p++]=i;
                for(i=0;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k;
                for(i=0;i<m;i++)c[i]=0;
                for(i=0;i<n;i++)c[x[y[i]]]++;
                for(i=0;i<m;i++)c[i]+=c[i-1];
                for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
                swap(x,y);
                p=1;x[sa[0]]=0;
                for(i=1;i<n;i++)
                x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
                if(p>=n)break;
                m=p;
            }
        }
        int rank[N],height[N];
        void getHeight(){
            int i,j,k=0;
            for(i=0;i<n;i++)rank[sa[i]]=i;
            for(i=0;i<n;i++){
                if(k)k--;
                int j=sa[rank[i]-1];
                while(s[i+k]==s[j+k])k++;
                height[rank[i]]=k;
            }
        }
        void rmq(){
            for(int i=1;i<n;i++)    f[i][0]=height[i];
            for(int j=1;j<20;j++)
                for(int i=1;i+(1<<j)-1<n;i++)
                    f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
        }
        int lcp(int l,int r){
            int k=log2(r-l+1);
            return min(f[l][k],f[r+1-(1<<k)][k]);
        }
        void bu(){
            for(int i=1;i<n;i++)
                update(rt[i],rt[i-1],sa[i]);
        }
        int work(int l,int r,int k){
            int po=rank[l-1];
            //cout<<po<<endl;
            int L,R,ans=-1; int mxl,mxr;
            L=1; R=po; mxl=mxr=po;
            while(L<=R){
                int mid=(L+R)>>1;
            //    cout<<L<<" "<<R<<" "<<mid<<" "<<lcp(mid,po)<<endl;
                if(lcp(mid,po)>=r-l+1){
                    R=mid-1;
                    ans=mid;
                }else{
                    L=mid+1;
                }
            }
            if(ans!=-1)
            mxl=ans;
            ans=-1;
            if(po<n-1){
                L=po+1; R=n-1;
                while(L<=R){
                //    cout<<L<<" "<<R<<endl;
                    int mid=(L+R)>>1;
                    if(lcp(po+1,mid)>=r-l+1){
                        L=mid+1;
                        ans=mid;
                    }else{
                        R=mid-1;
                    }
                }
                if(ans!=-1)
                mxr=ans;
            }
        //    cout<<n<<endl;
        //    cout<<mxl<<" "<<mxr<<endl;
            if(lcp(mxl,mxr)>=r-l+1){
                mxl=mxl-1;    
            }
            if(mxr-mxl+1<k) return -1;
            return query(rt[mxr],rt[mxl-1],k)+1;
        }
    }sa;
    char s[N];
    int main(){
    //    ios::sync_with_stdio(false);
    //    cin.tie(0); cout.tie(0);
        int t; scanf("%d",&t);
        while(t--){
            int n,q; scanf("%d%d",&n,&q);
            scanf("%s",s);
            nico=0;
            for(int i=0;i<n;i++)
                sa.s[i]=s[i]-'a'+1;
            sa.s[n]=0; sa.n=n+1;
            sa.build_sa(27); sa.getHeight();
            build(rt[0],0,N);
            sa.rmq(); sa.bu();
            for(int i=1;i<=q;i++){
                int l,r,k;
                scanf("%d%d%d",&l,&r,&k);
                printf("%d
    ",sa.work(l,r,k));
            }
        }
    }
    View Code
  • 相关阅读:
    iOS 苹果开发证书失效的解决方案(Failed to locate or generate matching signing assets)
    iOS NSArray数组过滤
    App Store2016年最新审核规则
    iOS 根据字符串数目,自定义Label等控件的高度
    iOS 证书Bug The identity used to sign the executable is no longer valid 解决方案
    Entity FrameWork 增删查改的本质
    EF容器---代理类对象
    Entity FrameWork 延迟加载本质(二)
    Entity FrameWork 延迟加载的本质(一)
    Entity FrameWork 增删查改
  • 原文地址:https://www.cnblogs.com/wmj6/p/11424935.html
Copyright © 2011-2022 走看看