zoukankan      html  css  js  c++  java
  • BJOI2020 封印

    封印

    给出只包含小写字母 (a,b) 的两个字符串 (s, t)(q) 次询问,每次询问 (s[l dots r])(t) 的最长公共子串长度。

    (nleq 2 imes 10^5)

    题解

    https://www.cnblogs.com/dysyn1314/p/13158865.html

    考虑预处理s的每个子串是不是t的子串。发现对于一个左端点(i (1leq ileq |s|)),一定存在一个(R[i]),使得(forall jin[i,R[i]]:s[idots j])都是(t)的子串,(forall kin[R[i]+1,n]:s[idots k])都不是(t)的子串。也就是说,使得(s[idots r])(t)子串的(r),一定是从(i)开始的一段连续的区间,而(R[i])就是其中最大的(r)。我们考虑把所有(R[i])预处理出来。

    从小到大枚举(i)。我们已经知道了(s[i-1dots R[i-1]])(t)的子串。那么,(s[idots R[i-1]])一定也是(t)的子串,也就是说,(R[i]geq R[i-1])。那么我们从(R[i-1]+1)开始,一位一位向后枚举,判断是否是(t)的子串。可以对(t)建一个SAM,这个“向后枚举”,就相当于在SAM上走转移边。同时,我们还要支持把前面的第(i-1)位删掉,这就相当于在SAM上跳父亲边。因为(R[i])是单调的,所以时间复杂度(O(|s|))(|s|,|t|)同阶)。

    预处理出(R)数组后,考虑回答询问。对于一个询问(l,r)。我们相当于要求出,(max_{i=l}^{r}{min(r,R[i])-i+1})。对于(min(r,R[i])),我们分类讨论:

    • 对于(R[i]leq r)(i),相当于询问(max_{lleq ileq r}{R[i]-i+1})

    • 对于(R[i]>r)(i),相当于询问(r+max_{lleq ileq r}{-i}+1)

    如果把(R[i])(r)的关系看做一维,(i)(l,r)的关系看做一维,那相当于是一个二维的区间最大值查询。可以考虑离线,把询问按右端点排序,这样(R[i])(r)的这一维就不存在了,我们只要做一维的区间最大值查询,可以用(两棵)线段树维护。

    时间复杂度(O(|s|+qlog |s|))

    CO int N=4e5+10,inf=1e9;
    namespace SAM{
    	int last=1,tot=1;
    	array<int,26> ch[N];
    	int fa[N],len[N];
    	
    	void extend(int c){
    		int x=last,cur=last=++tot;
    		len[cur]=len[x]+1;
    		for(;x and !ch[x][c];x=fa[x]) ch[x][c]=cur;
    		if(!x) {fa[cur]=1; return;}
    		int y=ch[x][c];
    		if(len[y]==len[x]+1) {fa[cur]=y; return;}
    		int clone=++tot;
    		ch[clone]=ch[y],fa[clone]=fa[y],len[clone]=len[x]+1;
    		fa[cur]=fa[y]=clone;
    		for(;ch[x][c]==y;x=fa[x]) ch[x][c]=clone;
    	}
    }
    
    struct SEG{
    	int tree[2*N];
    	
    	#define lc (x<<1)
    	#define rc (x<<1|1)
    	#define mid ((l+r)>>1)
    	IN void push_up(int x){
    		tree[x]=max(tree[lc],tree[rc]);
    	}
    	void build(int x,int l,int r,int v[N]){
    		if(l==r) {tree[x]=v[l]; return;}
    		build(lc,l,mid,v);
    		build(rc,mid+1,r,v);
    		push_up(x);
    	}
    	void insert(int x,int l,int r,int p,int v){
    		if(l==r) {tree[x]=v; return;}
    		if(p<=mid) insert(lc,l,mid,p,v);
    		else insert(rc,mid+1,r,p,v);
    		push_up(x);
    	}
    	int query(int x,int l,int r,int ql,int qr){
    		if(ql<=l and r<=qr) return tree[x];
    		if(qr<=mid) return query(lc,l,mid,ql,qr);
    		if(ql>mid) return query(rc,mid+1,r,ql,qr);
    		return max(query(lc,l,mid,ql,qr),query(rc,mid+1,r,ql,qr));
    	}
    	#undef lc
    	#undef rc
    	#undef mid
    }T1,T2;
    
    char s[N],t[N];
    int R[N],ans[N];
    struct event {int l,r,id;} e[N];
    
    int main(){
    	scanf("%s%s",s+1,t+1);
    	int n=strlen(s+1),m=strlen(t+1);
    	for(int i=1;i<=m;++i) SAM::extend(t[i]-'a');
    	int num=0;
    	for(int i=1,x=1;i<=n;++i){
    		using namespace SAM;
    		R[i]=max(R[i-1],i-1);
    		if(R[i]==i-1) x=1;
    		for(;x!=1 and len[fa[x]]+1>R[i]-i+1;x=fa[x]);
    		for(;R[i]+1<=n and ch[x][s[R[i]+1]-'a'];x=ch[x][s[R[i]+1]-'a'],++R[i]);
    		e[++num]={i,R[i],0};
    	}
    	int q=read<int>();
    	for(int i=1;i<=q;++i){
    		int l=read<int>(),r=read<int>();
    		e[++num]={l,r,i};
    	}
    	static int tmp[N];
    	for(int i=1;i<=n;++i) tmp[i]=-inf;
    	T1.build(1,1,n,tmp);
    	for(int i=1;i<=n;++i) tmp[i]=-i;
    	T2.build(1,1,n,tmp);
    	sort(e+1,e+num+1,[&](CO event&a,CO event&b)->bool{
    		return a.r!=b.r?a.r<b.r:a.id<b.id;
    	});
    	for(int i=1;i<=num;++i){
    		if(!e[i].id){
    			T1.insert(1,1,n,e[i].l,e[i].r-e[i].l+1);
    			T2.insert(1,1,n,e[i].l,-inf);
    		}
    		else{
    			int x=T1.query(1,1,n,e[i].l,e[i].r);
    			int y=e[i].r+T2.query(1,1,n,e[i].l,e[i].r)+1;
    			ans[e[i].id]=max(x,y);
    		}
    	}
    	for(int i=1;i<=q;++i) printf("%d
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    我的安全测试面试_自问自答,不亦乐乎
    Linux Shell 网络层监控脚本(监控包括:连接数、句柄数及根据监控反馈结果分析)
    netstat监控大量ESTABLISHED连接与Time_Wait连接问题
    详解 Spotlight on MySQL监控MySQL服务器
    详解 Spotlight on Unix 监控Linux服务器
    某听书网站系统漏洞,利用抓包拼接方式获取网站资源
    不懂得使用工具的测试不是好测试
    【好书摘要】性能优化中CPU、内存、磁盘IO、网络性能的依赖
    性能调优从哪里入手
    报文解析,从请求报文详细讲到响应码
  • 原文地址:https://www.cnblogs.com/autoint/p/13251559.html
Copyright © 2011-2022 走看看