zoukankan      html  css  js  c++  java
  • 【[HEOI2016/TJOI2016]字符串】

    码农题啊

    上来先无脑一个(SA)的板子,求出(SA)(het)数组

    我们只需要从(sa[i]in[a,b])的所有(i)中找到一个(i)使得(sa[i])(rk[c])之间的最小值最大就好了

    但是还必须得满足(sa[i]+lcp-1<=b),毕竟整个串还得在([a,b])内部

    考虑一下二分答案

    根据(het)数组的性质显然越靠近(rk[c])(sa[i])形成的(lcp)越长,于是我们可以利用一个(ST)表加二分找到从(rk[i])往前开始的一个尽量长的区间整个区间内的所有(het)大于等于当前二分出来的(mid)

    之后查一下这个区间内部有多少个在([a,b-mid+1])范围的(sa),这样如果存在任意一个数,就会满足条件

    可以用主席树来做到这一点

    代码

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #define re register
    #define LL long long
    #define maxn 100005
    #define M 5000005
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    inline int read()
    {
    	re char c=getchar();int x=0;
    	while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    int n,m,Q,cnt;
    char S[maxn];
    int rk[maxn],het[maxn],sa[maxn],tax[maxn],tp[maxn],rt[maxn],log_2[maxn];
    int St[maxn][18];
    int ls[M],rs[M],d[M];
    int change(int pre,int x,int y,int pos)
    {
    	int root=++cnt;
    	d[root]=d[pre]+1;
    	if(x==y) return root;
    	ls[root]=ls[pre],rs[root]=rs[pre];
    	int mid=x+y>>1;
    	if(pos<=mid) ls[root]=change(ls[pre],x,mid,pos);
    		else rs[root]=change(rs[pre],mid+1,y,pos);
    	return root;
    }
    inline void qsort()
    {
    	for(re int i=0;i<=m;i++) tax[i]=0;
    	for(re int i=1;i<=n;i++) tax[rk[i]]++;
    	for(re int i=1;i<=m;i++) tax[i]+=tax[i-1];
    	for(re int i=n;i;--i) sa[tax[rk[tp[i]]]--]=tp[i];
    }
    inline int ask(int l,int r)
    {
    	int k=log_2[r-l+1];
    	return min(St[l][k],St[r-(1<<k)+1][k]);
    }
    int query(int p1,int p2,int pos,int x,int y)
    {
    	if(x==y) return d[p2]-d[p1];
    	int mid=x+y>>1;
    	if(pos<=mid) return query(ls[p1],ls[p2],pos,x,mid);
    		return d[ls[p2]]-d[ls[p1]]+query(rs[p1],rs[p2],pos,mid+1,y);
    }
    inline int check(int now,int l,int r,int pos)
    {
    	int L=1,R=pos,to=0;
    	while(L<=R)
    	{
    		int mid=L+R>>1;
    		if(ask(mid,pos)>=now) R=mid-1,to=mid;
    			else L=mid+1;
    	}
    	if(to&&query(rt[to-2],rt[pos],r-now+1,1,n)-((l-1)?(query(rt[to-2],rt[pos],l-1,1,n)):0)) return 1; 
    	L=pos+1,R=n,to=0;
    	while(L<=R)
    	{
    		int mid=L+R>>1;
    		if(ask(pos+1,mid)>=now) L=mid+1,to=mid;
    			else R=mid-1;
    	}
    	if(to&&query(rt[pos-1],rt[to],r-now+1,1,n)-((l-1)?(query(rt[pos-1],rt[to],l-1,1,n)):0)) return 1;
    	return 0;
    }
    int main()
    {
    	n=read(),Q=read(),scanf("%s",S+1);
    	m=75;
    	for(re int i=1;i<=n;i++) 
    		rk[i]=S[i]-'a'+1,tp[i]=i;
    	qsort();
    	for(re int w=1,p=0;p<n;m=p,w<<=1)
    	{
    		p=0;
    		for(re int i=1;i<=w;i++) tp[++p]=n-w+i;
    		for(re int i=1;i<=n;i++) if(sa[i]>w) tp[++p]=sa[i]-w;
    		qsort();
    		for(re int i=1;i<=n;i++) std::swap(rk[i],tp[i]);
    		rk[sa[1]]=p=1;
    		for(re int i=2;i<=n;i++) rk[sa[i]]=(tp[sa[i-1]]==tp[sa[i]]&&tp[sa[i-1]+w]==tp[sa[i]+w])?p:++p;
    	}
    	int k=0;
    	for(re int i=1;i<=n;i++)
    	{
    		if(k) --k;
    		int j=sa[rk[i]-1];
    		while(S[i+k]==S[j+k]) ++k;
    		het[rk[i]]=k;
    	}
    	memset(St,20,sizeof(St));
    	int num=0;
    	for(re int i=2;i<=n;i++) log_2[i]=1+log_2[i/2];
    	for(re int i=1;i<=n;i++) St[i][0]=het[i];
    	for(re int j=1;j<=log_2[n];j++)
    		for(re int i=1;i+(1<<j)-1<=n;i++) St[i][j]=min(St[i][j-1],St[i+(1<<(j-1))][j-1]);
    	for(re int i=1;i<=n;i++)
    		rt[i]=change(rt[i-1],1,n,sa[i]);
    	while(Q--)
    	{
    		int x=read(),y=read(),xx=read(),yy=read();
    		int R=y-x+1,L=1,ans=0;
    		while(L<=R)
    		{
    			int mid=L+R>>1;
    			if(check(mid,x,y,rk[xx])) L=mid+1,ans=mid;
    				else R=mid-1;
    		}
    		ans=min(ans,yy-xx+1);
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    68
    56
    Django manager 命令笔记
    Django 执行 manage 命令方式
    Django 连接 Mysql (8.0.16) 失败
    Python django 安装 mysqlclient 失败
    H.264 SODB RBSP EBSP的区别
    FFmpeg—— Bitstream Filters 作用
    MySQL 远程连接问题 (Windows Server)
    MySQL 笔记
  • 原文地址:https://www.cnblogs.com/asuldb/p/10205627.html
Copyright © 2011-2022 走看看