Luogu P4482 [BJWC2018]Border 的四种求法

Posted cjoiershiina-mashiro

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Luogu P4482 [BJWC2018]Border 的四种求法相关的知识,希望对你有一定的参考价值。

Link
(s(l,r))的border相当于求(max{iin[l,r)|lcs(i,r)>i-l})
在SAM上就相当于是求(max{iin[l,r)|len(lca(i,r))>i-l})
考虑把parent树重链剖分,那么(r)到根的路径就会被拆成(log)条重链的前缀。
对于重链上的点(u),如果(u)(lca(i,r))的话,那么(i)要么是(u),要么就是其轻子树中的节点,这可以暴力统计。
将限制条件移项变成(i-len(lca(i,r))<l),那么我们要求的就是求(max{iin[l,r)|i-len(u)<l}),其中(u)是重链上的某个点,(i)(u)轻子树中的某个点。
这对每个重链维护一棵线段树,查询时在线段树上二分即可。
考虑轻重链切换的情况,设跳到新的重链上的点(u),我们需要统计之前那条重链所在子树以外的答案。因为(len)是随深度递减而递减的,因此之前那条重链所在子树的点(i)(u)处再统计一遍答案一定不会更优。那么我们每个点开个线段树并用线段树合并维护即可。
一次询问中能够产生贡献的是重链的前缀,因此我们把询问拆成(log)条重链的前缀并挂在树上,最后一次dfs统计即可。

#include<cctype>
#include<cstdio>
#include<vector>
#include<cstring>
#include<utility>
#include<algorithm>
using pi=std::pair<int,int>;
const int N=400007;
char str[N];int ans[N];
struct node{int id,l,r;};
int read(){int x=0,c=getchar();while(isspace(c))c=getchar();while(isdigit(c))(x*=10)+=c&15,c=getchar();return x;}
struct SegTree
{
#define mid ((l+r)/2)
    int t[N*20],ls[N*20],rs[N*20],root[N],tot;
    SegTree(){memset(t,0x7f,sizeof t);}
    void pushup(int p){t[p]=std::min(t[ls[p]],t[rs[p]]);}
    void insert(int&p,int l,int r,int x,int v)
    {
	if(!p) p=++tot;
	if(l==r) return t[p]=std::min(t[p],v),void();
	x<=mid? insert(ls[p],l,mid,x,v):insert(rs[p],mid+1,r,x,v),pushup(p);
    }
    int query(int p,int l,int r,int x,int lim)
    {
	int now=0;
	if(!p||t[p]>=lim) return 0;
	if(l==r) return l;
	if(x<=mid+1) return query(ls[p],l,mid,x,lim);
	if(t[rs[p]]<lim) now=query(rs[p],mid+1,r,x,lim);
	return now? now:query(ls[p],l,mid,x,lim);
    }
    int merge(int u,int v,int l,int r)
    {
	if(!u||!v) return u|v;
	int p=++tot;
	if(l==r) t[p]=std::min(t[u],t[v]); else ls[p]=merge(ls[u],ls[v],l,mid),rs[p]=merge(rs[u],rs[v],mid+1,r),pushup(p);
	return p;
    }
}t1,t2;
struct Automaton
{
    std::vector<int>e[N];std::vector<pi>s[N];std::vector<node>q[N];
    int cnt=1,now=1,trans[N][26],len[N],link[N],id[N],pos[N],size[N],top[N],son[N];
    void extend(int c)
    {
	int p=now,q;now=++cnt,id[now]=len[now]=len[p]+1,pos[len[p]+1]=now;
	for(;p&&!trans[p][c];p=link[p]) trans[p][c]=now;
	if(!p) return link[now]=1,void();
	if(len[q=trans[p][c]]==len[p]+1) return link[now]=q,void();
	link[++cnt]=link[q],memcpy(trans[cnt],trans[q],104),len[cnt]=len[p]+1,link[now]=link[q]=cnt,pos[cnt]=pos[q];
	for(;trans[p][c]==q;p=link[p]) trans[p][c]=cnt;
    }
    void dfs1(int u)
    {
	if(id[u]) t1.insert(t1.root[u],1,cnt,id[u],id[u]);
	size[u]=1;
	for(int v:e[u]) if(dfs1(v),t1.root[u]=t1.merge(t1.root[u],t1.root[v],1,cnt),size[u]+=size[v],size[v]>size[son[u]]) son[u]=v;
    }
    void init(int u,int rt)
    {
	if(id[u]) s[rt].emplace_back(id[u],id[u]-len[rt]);
	for(int v:e[u]) init(v,rt);
    }
    void dfs2(int u,int tp)
    {
	top[u]=tp;
	if(id[u]) s[u].emplace_back(id[u],id[u]-len[u]);
	if(son[u]) dfs2(son[u],tp);
	for(int v:e[u]) if(v^son[u]) dfs2(v,v),init(v,u);
    }
    void build()
    {
	for(int i=2;i<=cnt;++i) e[link[i]].push_back(i);
	dfs1(1),dfs2(1,1);
    }
    int query(int u,int l,int r,node qry)
    {
	int ans=0;
	for(;u;u=link[top[u]]) q[u].push_back(qry),ans=std::max(ans,t1.query(t1.root[u],1,cnt,r,l+len[u]));
	return std::max(0,ans-l+1);
    }
    void solve(int u)
    {
	for(pi x:s[u]) t2.insert(t2.root[top[u]],1,cnt,x.first,x.second);
	for(auto[id,l,r]:q[u]) ans[id]=std::max(ans[id],std::max(0,t2.query(t2.root[top[u]],1,cnt,r,l)-l+1));
	for(int v:e[u]) solve(v);
    }
}sam;
int main()
{
    scanf("%s",str+1);int n=strlen(str+1),m=read();
    for(int i=1;i<=n;++i) sam.extend(str[i]-‘a‘);
    sam.build();
    for(int i=1,l,r;i<=m;++i) l=read(),r=read(),ans[i]=sam.query(sam.pos[r],l,r,node{i,l,r});
    sam.solve(1);
    for(int i=1;i<=m;++i) printf("%d
",ans[i]);
}








以上是关于Luogu P4482 [BJWC2018]Border 的四种求法的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3782&luogu4478 [BJWC2018]上学路线

[luogu4479][BJWC2018]第k大斜率二维偏序+二分+离散化+树状数组

[luogu4478 BJWC2018] 上学路线 (容斥原理+拓展lucas)

BZOJ1229 & 洛谷2917:[USACO2008 NOV]toy 玩具 & 洛谷4480:[BJWC2018]餐巾计划问题——题解

luogu_P4822 [BJWC2012]冻结

Luogu P4570 [BJWC2011]元素