zoukankan      html  css  js  c++  java
  • LOJ#2059. 「TJOI / HEOI2016」字符串 后缀数组+二分+主席树

    后缀自动机的做法很显然:建出后缀树,线段树合并,然后倍增的时候更新答案就行.

    后缀数组的做法也挺显然:二分答案,然后用主席树判定一下 $[a,b-mid+1]$ 是否有值即可.    

    code: 

    #include <bits/stdc++.h> 
    #define N 200006   
    #define lson s[x].ls 
    #define rson s[x].rs 
    #define inf 1000000000 
    #define setI(s) freopen(s".in","r",stdin)   
    #define setO(s) freopen(s".out","w",stdout)  
    using namespace std;  
    int n,tot,m;   
    int rt[N];   
    int arr[N],rk[N],tp[N],tax[N],sa[N],height[N],Log[N],dp[20][N];    
    void qsort() 
    {
        for(int i=0;i<=m;++i)  tax[i]=0;   
        for(int i=1;i<=n;++i)  ++tax[rk[i]];   
        for(int i=1;i<=n;++i)  tax[i]+=tax[i-1];   
        for(int i=n;i>=1;--i)  sa[tax[rk[tp[i]]]--]=tp[i];    
    }
    void getsuf() 
    {
        for(int i=1;i<=n;++i) rk[i]=arr[i],tp[i]=i; 
        qsort();   
        for(int k=1;k<=n;k<<=1) 
        {
            int p=0;   
            for(int i=n-k+1;i<=n;++i) tp[++p]=i;   
            for(int i=1;i<=n;++i) if(sa[i]>k) tp[++p]=sa[i]-k;    
            qsort(),swap(rk,tp),rk[sa[1]]=p=1;   
            for(int i=2;i<=n;++i)  
                rk[sa[i]]=(tp[sa[i-1]]==tp[sa[i]]&&tp[sa[i-1]+k]==tp[sa[i]+k])?p:++p;      
            if(p==n) break;    
            m=p;
        }  
        for(int i=1;i<=n;++i) rk[sa[i]]=i;   
        for(int i=1,k=0;i<=n;++i)
        { 
            if(k) --k;   
            int j=sa[rk[i]-1];   
            while(arr[i+k]==arr[j+k]) ++k;   
            height[rk[i]]=k;            
        }     
    }               
    void RMQ() 
    {
        for(int i=2;i<=n;++i) Log[i]=Log[i>>1]+1;   
        for(int i=1;i<=n;++i) dp[0][i]=height[i];         
        for(int j=1;(1<<j)<=n;++j)  
            for(int i=1;i+(1<<j)-1<=n;++i)   
                dp[j][i]=min(dp[j-1][i],dp[j-1][i+(1<<j-1)]);          
    }
    int getmin(int l,int r) 
    {
        int k=Log[r-l+1];    
        return min(dp[k][l],dp[k][r-(1<<k)+1]);   
    }
    struct data 
    {
        int ls,rs,sum;   
        data() { ls=rs=sum=0; }   
    }s[N*25];            
    void pushup(int x) 
    {
        s[x].sum=s[lson].sum+s[rson].sum;     
    }
    int update(int x,int l,int r,int p) 
    { 
        int now=++tot;    
        s[now]=s[x];         
        s[now].sum++;  
        if(l==r)  return now; 
        int mid=(l+r)>>1;   
        if(p<=mid)  s[now].ls=update(s[x].ls,l,mid,p);  
        else s[now].rs=update(s[x].rs,mid+1,r,p);      
        return now;   
    }         
    int query(int x,int y,int l,int r,int L,int R) 
    {
        if(!x) return 0;  
        if(l>=L&&r<=R) return s[y].sum-s[x].sum;     
        int mid=(l+r)>>1,re=0;  
        if(L<=mid)  re+=query(s[x].ls,s[y].ls,l,mid,L,R);  
        if(R>mid)   re+=query(s[x].rs,s[y].rs,mid+1,r,L,R);   
        return re;  
    }
    void build(int &x,int l,int r) 
    {
        s[x=++tot].sum=0;  
        if(l==r) return;   
        int mid=(l+r)>>1;  
        build(lson,l,mid),build(rson,mid+1,r);  
    }
    char str[N];  
    int main()    
    {  
        int Q; 
        scanf("%d%d%s",&n,&Q,str+1);    
        for(int i=1;i<=n;++i) arr[i]=str[i]-'a'+1;   
        m=27,getsuf(),RMQ(),build(rt[0],1,n); 
        for(int i=1;i<=n;++i)
            rt[i]=update(rt[i-1],1,n,sa[i]);      
        int a,b,c,d,l,r,mid,an,lp,rp,L,R; 
        while(Q--) 
        { 
            scanf("%d%d%d%d",&a,&b,&c,&d);              
            l=1,r=min(d-c+1,b-a+1),mid=0,an=0; 
            while(l<=r) 
            {
                mid=(l+r)>>1;  
                L=R=rk[c];   
                lp=1,rp=rk[c]-1;      
                while(lp<=rp) 
                {
                    int tmp=(lp+rp)>>1;   
                    if(getmin(tmp+1,rk[c])>=mid) L=tmp,rp=tmp-1;  
                    else lp=tmp+1;       
                }  
                lp=rk[c]+1,rp=n;   
                while(lp<=rp) 
                {
                    int tmp=(lp+rp)>>1;                                                               
                    if(getmin(rk[c]+1,tmp)>=mid) R=tmp,lp=tmp+1;  
                    
                    else rp=tmp-1;  
                }  
                // [lp,rp]        
                if(query(rt[L-1],rt[R],1,n,a,b-mid+1))   
                    an=mid,l=mid+1;   
                else r=mid-1; 
            }   
            printf("%d
    ",an);   
        }
        return 0; 
    }
    

      

  • 相关阅读:
    Unix命令大全
    vs2008 与 IE8出现的兼容性问题
    Java 创建文件、文件夹以及临时文件
    如何修改Wamp中mysql默认空密码
    PAT 乙级真题 1003.数素数
    Tags support in htmlText flash as3
    DelphiXE4 FireMonkey 试玩记录,开发IOS应用 还是移植
    10 Great iphone App Review sites to Promote your Apps!
    HTML tags in textfield
    Delphi XE4 IOS 开发, "No eligible applications were found“
  • 原文地址:https://www.cnblogs.com/guangheli/p/13035936.html
Copyright © 2011-2022 走看看