zoukankan      html  css  js  c++  java
  • [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;
            }
    
        }
    }
    

      

     
  • 相关阅读:
    GitHub 源码,Framework 框架
    转int啥啥啥的
    查看apk签名 和 keystore 的信息
    一次apk打开时报内存溢出错误,故写下内存溢出的各种原因和解决方法
    客户端传值里面包含URL特殊字符的应对方法
    Linux全硬盘搜索文件名是xxxxx的命令
    pythonmysql运行报错解决过程中遇到的其中一个报错解决文章来源
    linux查看硬盘占用情况
    Linux使用nginx反向代理。可实现域名指向特定端口
    Linux下使用yum安装软件命令
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/11420878.html
Copyright © 2011-2022 走看看