• K-th occurrence HDU


    大意: 给定串sq个询问(l,r,k), 求子串s[l,r]的第kk次出现位置.

    这是一篇很好的题解:

    https://blog.csdn.net/sdauguanweihong/article/details/100063096

    加点个人:

    我对上面的题解更为详细的解释下:

    后缀数组处理出来的heigth[] 数组 有个这样的性质:  

    对于排名 a 的后缀字符串 与排名 b 的后缀字符串  ,他们的最长公共前缀的长度为 min{heigth[a+1],heigth[a+2],heigth[b]};

    依据这样的性质就可以二分线段树出[l,r] 这个字符串 是在多少排名的区间[L,R]了;

    注意:我本想贪图方便用先二分l然后判断[l,pos] 的最小值复杂度为log*log  这个会T的

    所以找这个区间要用log的方法,就是在存了最小值的线段树里面去搜左孩子啊右孩子什么的

    #include<bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    const int maxn = 1000050;
    char s[maxn];
    int y[maxn],x[maxn],c[maxn],sa[maxn],rk[maxn],height[maxn],wt[30];
    int n,k,q;
    
    int get_SA(int m){
        for(int i=0 ; i<=m ; i++) c[i]=0;
        for(int i=0 ; i<=n ; i++) sa[i]=0;
        for(int i=1 ; i<=n ; i++) ++c[x[i]=s[i]];
        for(int i=2 ; i<=m ; i++) c[i]+=c[i-1];
        for(int i=n ; i>=1 ; i--) sa[c[x[i]]--]=i;
        for(int k=1 ; k<=n ; k<<=1){
            int num=0;
            for(int i=n-k+1 ; i<=n ; i++) y[++num]=i;
            for(int i=1 ; i<=n ; i++) if(sa[i]>k) y[++num]=sa[i]-k;
            for(int i=1 ; i<=m ; i++) c[i]=0;
            for(int i=1 ; i<=n ; i++) ++c[x[i]];
            for(int i=2 ; i<=m ; i++) c[i]+=c[i-1];
            for(int i=n ; i>=1 ; i--) sa[c[x[y[i]]]--]=y[i],y[i]=0;
            swap(x,y);
            x[sa[1]]=1;
            num=1;
            for(int i=2 ; i<=n ; i++)
                x[sa[i]]=(y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k]) ? num : ++num;
                if (num==n) break;
                m=num;
        }
    }
    int get_height() {
        int k=0;
        for (int i=1; i<=n; ++i) rk[sa[i]]=i;
        for (int i=1; i<=n; ++i) {
            if (rk[i]==1) continue;
            if (k) --k;
            int j=sa[rk[i]-1];
            while (j+k<=n && i+k<=n && s[i+k]==s[j+k]) ++k;
            height[rk[i]]=k;
        }
    }
    
    int mi[maxn<<2];
    void pushup(int rt){
        mi[rt]=min(mi[rt<<1],mi[rt<<1|1]);
    }
    void build(int l,int r,int rt)
    {
        if ( l==r )
        {
            mi[rt]=height[l];
            return ;
        }
        int m = (l+r) >> 1;
        build(l,m,rt<<1);
        build(m+1,r,rt<<1|1);
        pushup(rt);
    }
    
    int solvel(int o , int l , int r , int x , int v){
        int mid=(l+r)>>1;
        if(r<=x){
            if(l==r) return mi[o]>=v?l:-1;
            if(mi[o<<1|1]<v) return solvel(o<<1|1,mid+1,r,x,v);
            int t=solvel(o<<1,l,mid,x,v);
            return t==-1?mid+1:t;
        }
        if(mid>=x) return solvel(o<<1,l,mid,x,v);
        int R=solvel(o<<1|1,mid+1,r,x,v);
        if (R==-1||R>mid+1) return R;
        int L = solvel(o<<1,l,mid,x,v);
        return L==-1?R:L;
    }
    
    int solver(int o, int l, int r, int x, int v){
        int mid=(l+r)>>1;
        if (x<=l) {
            if (l==r) return mi[o]>=v?l:-1;
            if (mi[o<<1]<v) return solver(o<<1,l,mid,x,v);
            int t = solver(o<<1|1,mid+1,r,x,v);
            return t==-1?mid:t;
        }
        if (mid<x) return solver(o<<1|1,mid+1,r,x,v);
        int L = solver(o<<1,l,mid,x,v);
        if (L==-1||L<mid) return L;
        int R = solver(o<<1|1,mid+1,r,x,v);
        return R==-1?L:R;
    }
    
    int tot;
    int lson[maxn<<5],rson[maxn<<5],T[maxn],cc[maxn<<5];
    void zhu_build(int &root,int l,int r)
    {
        root=++tot;
        if ( l==r ) return;
        int mid=(l+r)/2;
        zhu_build(lson[root],l,mid);
        zhu_build(rson[root],mid+1,r);
    }
    void update(int root,int &rt,int p,int val,int l,int r)
    {
        rt=++tot;
        lson[rt]=lson[root],rson[rt]=rson[root];
        cc[rt]=cc[root]+val;
        if ( l==r ) return;
        int mid=(l+r)/2;
        if ( p<=mid ) update(lson[rt],lson[rt],p,val,l,mid);
        else update(rson[rt],rson[rt],p,val,mid+1,r);
    }
    int query(int rt_,int rt,int l,int r,int k)
    {
        if ( l==r ) return l;
        int mid=(l+r)/2;
        int sum=cc[lson[rt_]]-cc[lson[rt]];
        if ( sum>=k ) return query(lson[rt_],lson[rt],l,mid,k);
        else return query(rson[rt_],rson[rt],mid+1,r,k-sum);
    }
    
    int main(){
        int _;scanf("%d",&_);
        while(_--){
        scanf("%d%d%s",&n,&q,s+1);
    
        get_SA(122);
    
        get_height();
        build(1,n,1);
        tot=0;
        zhu_build(T[0],1,n);
        for(int i=1 ; i<=n ; i++){
            update(T[i-1],T[i],sa[i],1,1,n);
    
        }
        while(q--){
            int l,r;scanf("%d%d%d",&l,&r,&k);
            int p=rk[l];
        int ql = p>1?solvel(1,1,n,p,r-l+1)-1:1;
        int qr = p<n?solver(1,1,n,p+1,r-l+1):n;
        if (ql<0) ql = p;
        if (qr<0) qr = p;
            int ans;
            if(qr-ql+1<k)
            ans=-1;
            else
            ans=query(T[qr],T[ql-1],1,n,k);
    
            printf("%d
    ",ans);
        }
        }
    }
    View Code
  • 相关阅读:
    Nginx使用GeoIP模块来限制地区访问
    CenTOS7使用ACL控制目录权限,只给某个用户访问特定目录
    CentOS配置服务开机自启
    设置普通用户输入sudo,免密进入root账户
    Centos安装git并配置ssh
    ThreadLocal线程隔离
    Spring cloud 超时配置总结
    Hystrix超时测试
    mysql limit分页查询效率比拼
    linux CPU100%异常排查
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/11419023.html
Copyright © 2020-2023  润新知