zoukankan      html  css  js  c++  java
  • 【BZOJ4556】【TJOI2016&HeOI2016】—字符串(后缀数组+主席树+ST表)

    传送门

    先建出SaSa,考虑二分串的长度,判断可行

    显然和CC这个串的lcp>=midlcp>=mid的那些rankrank相连的一块都是满足的

    那我们就只需要查询是否有串在aa~bb的子串内
    rkrk建一颗主席树,区间查询就可以了

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    inline int read(){
    	char ch=getchar();
    	int res=0,f=1;
    	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=getchar();
    	return res*f;
    }
    const int N=200005;
    const int Log=21;
    int n,m,q,a[N],lg[N];
    char s[N];
    #define mid ((l+r)>>1)
    struct President_Tree{
    	int tot,rt[N],lc[N<<5],rc[N<<5],sum[N<<5];
    	void insert(int &now,int u,int l,int r,int p){
    		now=++tot,lc[now]=lc[u],rc[now]=rc[u],sum[now]=sum[u]+1;
    		if(l==r)return;
    		if(p<=mid)insert(lc[now],lc[u],l,mid,p);
    		else insert(rc[now],rc[u],mid+1,r,p);
    	}
    	int query(int r1,int r2,int l,int r,int st,int des){
    		if(st<=l&&r<=des)return sum[r2]-sum[r1];
    		int res=0;
    		if(st<=mid)res+=query(lc[r1],lc[r2],l,mid,st,des);
    		if(mid<des)res+=query(rc[r1],rc[r2],mid+1,r,st,des);
    		return res;
    	}
    }Seg;
    #undef mid
    struct Sa{
    	int rk[N],sa[N],sa2[N],cnt[N],ht[N],st[Log][N<<1];
    	inline void bucket_sort(){
    		for(int i=1;i<=m;i++)cnt[i]=0;
    		for(int i=1;i<=n;i++)++cnt[rk[sa2[i]]];
    		for(int i=1;i<=m;i++)cnt[i]+=cnt[i-1];
    		for(int i=n;i>=1;i--)sa[cnt[rk[sa2[i]]]--]=sa2[i];
    	}
    	inline void buildsa(){
    		m=50;
    		for(int i=1;i<=n;i++)rk[i]=a[i],sa2[i]=i;
    		bucket_sort();
    		for(int i=1,pos=0;i<=n&&pos<n;i<<=1){
    			pos=0;
    			for(int j=n-i+1;j<=n;j++)sa2[++pos]=j;
    			for(int j=1;j<=n;j++)if(sa[j]>i)sa2[++pos]=sa[j]-i;
    			bucket_sort();
    			swap(rk,sa2);
    			rk[sa[1]]=1,pos=1;
    			for(int j=2;j<=n;j++)
    				rk[sa[j]]=((sa2[sa[j]]==sa2[sa[j-1]])&&(sa2[sa[j]+i]==sa2[sa[j-1]+i])?pos:++pos);
    			m=pos;
    		}
    		for(int i=1;i<=n;i++)rk[sa[i]]=i;
    		for(int i=1,k=0,j;i<=n;ht[rk[i++]]=k){
    			for(k?k--:0,j=sa[rk[i]-1];a[i+k]==a[j+k];k++);
    		}
    	}
    	inline void init(){
    		for(int i=1;i<=n;i++)st[0][i]=ht[i];
    		for(int j=1;(1<<j)<=n;j++)
    			for(int i=1;i+(1<<j)-1<=n;i++)
    				st[j][i]=min(st[j-1][i],st[j-1][i+(1<<(j-1))]);
    	}
    }T;
    int main(){
        n=read(),q=read();
        scanf("%s",s+1);
        for(int i=1;i<=n;i++)a[i]=s[i]-'a'+1;
        T.buildsa(),T.init();
        for(int i=1;i<=n;i++)Seg.insert(Seg.rt[i],Seg.rt[i-1],1,n,T.rk[i]);
        while(q--){
            int A=read(),B=read(),C=read(),D=read();
            int ans=0,l=0,r=min(B-A,D-C)+1;
            while(l<=r){
            	int mid=(l+r)>>1;
            	int st=T.rk[C],des=T.rk[C];
            	for(int i=20;~i;i--)if(st>=(1<<i)&&T.st[i][st-(1<<i)+1]>=mid)st-=(1<<i);
            	for(int i=20;~i;i--)if(des+(1<<i)<=n&&T.st[i][des+1]>=mid)des+=(1<<i);
                if(Seg.query(Seg.rt[A-1],Seg.rt[B-mid+1],1,n,st,des)>0)ans=mid,l=mid+1;
                else r=mid-1;
            }
            cout<<ans<<'
    ';
        }
    }
    
  • 相关阅读:
    JSON Web Token 使用详解
    Linux文件同步工具之rsync
    Centos7升级Git版本
    JSON Web Token 使用详解
    解决List遍历删除元素提示ConcurrentModificationException
    Spring Boot入门篇之配置Filter
    通过PLSQL Developer创建Database link,DBMS_Job,Procedure,实现Oracle跨库传输数据
    微信运动数据抓取(PHP)
    使用Redis Data Reveal(rdr)查看Redis中key占用内存空间
    Redis5.0-弃用方法名和替代方法名(php-redis 5以后废弃了一些方法名)
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/11145638.html
Copyright © 2011-2022 走看看