zoukankan      html  css  js  c++  java
  • bzoj 3145 [Feyat cup 1.5]Str

    权限题

    这题暴力就是两个串分别枚举点(i,j),假设这两个点不同,那么剩下的部分就是尽量越长越好,所以这部分答案就是第一个串(i-1)前缀和第二个串(j-1)前缀的(lcs)+第一个串(i+1)后缀和第二个串(j+1)后缀的(lcp)+1

    考虑把两个串接起来,中间用个没用过的字符隔开,那么两个串前缀的(lcs)就可以先在前缀树上找到对应的两个点,然后就是两点(lca)(length).后缀的(lcp)也类似.那么答案就是(max (lcs(a_{i-1},a_{j-1})+lcp(b_{i+1},b_{j+1}))),其中(a_i)为某前缀在前缀树上对应点,(b_i)为后缀在后缀树上对应点

    所以这个问题变成了询问所有点对在两棵树上lca深度和的最大值.可以dfs第一棵树,然后处理第一棵树上lca为(x)的点对,每次把儿子内点在第二棵树的信息合并过来,就能求解.首先,两个子树合并,为了保证复杂度,需要启发式合并,然后在合并时算贡献.现在就是要知道某个点和一个点集内点在第二棵树上的lca最大深度,容易发现一定和dfs序相邻的点lca最深.所以一个点维护的是子树内点在第二棵树上以dfs序为关键字的set,每次二分查找前驱后继即可

    #include<bits/stdc++.h>
    #define LL long long
    #define uLL unsigned long long
    #define db double
    
    using namespace std;
    const int N=2e5+10;
    LL rd()
    {
    	LL x=0,w=1;char ch=0;
    	while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    	return x*w;
    }
    struct SAM
    {
    	int fa[N<<1],ch[N<<1][28],len[N<<1],la,tt;
    	int ps[N],px[N<<1],sz[N<<1],de[N<<1],hs[N<<1],top[N<<1],dfn[N<<1],ti;
    	vector<int> e[N<<1];
    	SAM(){la=tt=1;}
    	void extd(int cx,int ii)
    	{
    		int np=++tt,p=la;
    		len[np]=len[p]+1,ps[ii]=np,px[np]=ii,la=np;
    		while(!ch[p][cx]) ch[p][cx]=np,p=fa[p];
    		if(!p) fa[np]=1;
    		else
    		{
    			int q=ch[p][cx];
    			if(len[q]==len[p]+1) fa[np]=q;
    			else
    			{
    				int nq=++tt;
    				fa[nq]=fa[q],len[nq]=len[p]+1;
    				memcpy(ch[nq],ch[q],sizeof(ch[q]));
    				fa[np]=fa[q]=nq;
    				while(ch[p][cx]==q) ch[p][cx]=nq,p=fa[p];
    			}
    		}
    	}
    	void dfs1(int x)
    	{
    		sz[x]=1;
    		vector<int>::iterator it;
    		for(it=e[x].begin();it!=e[x].end();++it)
    		{
    			int y=*it;
    			de[y]=de[x]+1,dfs1(y);
    			sz[x]+=sz[y],hs[x]=sz[hs[x]]>sz[y]?hs[x]:y;
    		}
    	}
    	void dfs2(int x,int ntp)
    	{
    		dfn[x]=++ti,top[x]=ntp;
    		if(hs[x]) dfs2(hs[x],ntp);
    		vector<int>::iterator it;
    		for(it=e[x].begin();it!=e[x].end();++it)
    		{
    			int y=*it;
    			if(y==hs[x]) continue;
    			dfs2(y,y);
    		}
    	}
    	void inii()
    	{
    		for(int i=2;i<=tt;++i) e[fa[i]].push_back(i);
    		dfs1(1),dfs2(1,1);
    	}
    	int glca(int x,int y)
    	{
    		while(top[x]!=top[y])
    		{
    			if(de[top[x]]<de[top[y]]) swap(x,y);
    			x=fa[top[x]];
    		}
    		return de[x]<de[y]?x:y;
    	}
    }t1,t2;
    int n,m,ans;
    char cc[N];
    struct node
    {
    	int x;
    	bool operator < (const node &bb) const {return t2.dfn[x]<t2.dfn[bb.x];}
    };
    multiset<node> s1[N<<1],s2[N<<1];
    multiset<node>::iterator i1,i2,ft,nt,zr;
    int id[N<<1],tot;
    void dfs(int x)
    {
    	vector<int>::iterator it;
    	id[x]=x;
    	if(t1.px[x])
    	{
    		if(t1.px[x]+1<=n+1) s1[id[x]].insert((node){t2.ps[t1.px[x]+2]});
    		else if(t1.px[x]+1>n+2&&t1.px[x]+2<=n+m+2) s2[id[x]].insert((node){t2.ps[t1.px[x]+2]});
    	}
    	for(it=t1.e[x].begin();it!=t1.e[x].end();++it)
    	{
    		int y=*it;
    		dfs(y);
    		if(s1[id[x]].size()+s2[id[x]].size()<s1[id[y]].size()+s2[id[y]].size()) swap(id[x],id[y]);
    		bool fg1=!s1[id[x]].empty(),fg2=!s2[id[x]].empty();
    		if(fg2)
    		{
    			for(i1=s1[id[y]].begin();i1!=s1[id[y]].end();++i1)
    			{
    				int xx=(*i1).x;
    				nt=s2[id[x]].upper_bound(*i1);
    				if(nt!=s2[id[x]].begin()) ft=--nt,++nt;
    				else ft=zr;
    				if((*ft).x) ans=max(ans,t1.len[x]+t2.len[t2.glca((*ft).x,xx)]+1);
    				if(nt!=s2[id[x]].end()) ans=max(ans,t1.len[x]+t2.len[t2.glca((*nt).x,xx)]+1);
    			}
    		}
    		if(fg1)
    		{
    			for(i2=s2[id[y]].begin();i2!=s2[id[y]].end();++i2)
    			{
    				int xx=(*i2).x;
    				nt=s1[id[x]].upper_bound(*i2);
    				if(nt!=s1[id[x]].begin()) ft=--nt,++nt;
    				else ft=zr;
    				if((*ft).x) ans=max(ans,t1.len[x]+t2.len[t2.glca((*ft).x,xx)]+1);
    				if(nt!=s1[id[x]].end()) ans=max(ans,t1.len[x]+t2.len[t2.glca((*nt).x,xx)]+1);
    			}
    		}
    		for(i1=s1[id[y]].begin();i1!=s1[id[y]].end();++i1) s1[id[x]].insert(*i1);
    		for(i2=s2[id[y]].begin();i2!=s2[id[y]].end();++i2) s2[id[x]].insert(*i2);
    	}
    }
    
    int main()
    {
    	cc[1]='|';
    	scanf("%s",cc+2);
    	n=strlen(cc+2);
    	cc[n+2]='{';
    	scanf("%s",cc+n+3);
    	m=strlen(cc+n+3);
    	for(int i=1;i<=n+m+2;++i) t1.extd(cc[i]-'a',i);
    	t1.inii();
    	for(int i=n+m+2;i;--i) t2.extd(cc[i]-'a',i);
    	t2.inii();
    	s1[0].insert((node){0});
    	zr=s1[0].begin();
    	dfs(1);
    	printf("%d
    ",ans);
    	return 0; 
    }
    
  • 相关阅读:
    阿里DatatX mysql8往 Elasticsearch 7 插入时间数据 时区引发的问题
    通俗易懂 k8s (3):kubernetes 服务的注册与发现
    ReplicaSet 和 ReplicationController 的区别
    使用Go module导入本地包
    k8s之statefulset控制器
    终于成功部署 Kubernetes HPA 基于 QPS 进行自动伸缩
    Atitit drmmr outline org stat vb u33.docx Atitit drmmr outline org stat v0 taf.docx Atitit drmmr out
    Atitit all diary index va u33 #alldiary.docx Atitit alldiaryindex v1 t717 目录 1. Fix 1 2. Diary deta
    Atitit path query 路径查询语言 数据检索语言 目录 1.1. List map >> spel 1 1.2. Html数据 》》Css选择符 1 1.3. Json 》map》
    Atitit prgrmlan topic--express lan QL query lan表达式语言 目录 1. 通用表达语言(CEL) 1 1.1. 8.2 功能概述 1 1.2. Ongl
  • 原文地址:https://www.cnblogs.com/smyjr/p/11524303.html
Copyright © 2011-2022 走看看