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

    题目传送门

    分析:
    对于每一个左端点(l),我们都能找到一个(r),使得(l leq j leq r)(S_{l,j})(T)的子串,(j geq r)(S_{l,j})不为(T)的子串
    (l)增大时,对应的(r)单调不降,尝试求出每一个(l)对应的(r)
    考虑建一个SAM,目前的(S_{l,r})对应的子串所在节点为(p)(r)加一位,相当于沿着字符转移边跳一步
    如果目前节点子串集合最短长度(即父亲的(len)加一)大于了(r-l+1),则(p)往后缀树上的父亲跳一步
    复杂度是(O(n))
    找到了每一个位置(i)对应的(r_i),考虑询问(L,R)
    需要分(r_i leq R)(r_i>R)分类讨论
    我们对询问离线,两种情况分两棵线段树,单点修改区间取最大值可以简单维护

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    #include<queue>
    #include<bitset>
    #include<map>
    #include<set>
    
    #define maxn 400005
    #define INF 0x3f3f3f3f
    
    using namespace std;
    
    inline int getint()
    {
    	int num=0,flag=1;char c;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
    	return num*flag;
    }
    
    int n;
    struct Sam{
    	int fa,len,nxt[26];
    }t[maxn];
    char S[maxn],T[maxn];
    int lst,tot,cnt;
    int ans[maxn];
    struct node{
    	int l,r,op,id;
    }q[maxn];
    inline bool cmp(node x,node y)
    {return x.r==y.r?x.op<y.op:x.r<y.r;}
    
    inline void ins(int c)
    {
    	int p=lst,np=lst=++tot;
    	t[np].len=t[p].len+1;
    	while(p&&!t[p].nxt[c])t[p].nxt[c]=np,p=t[p].fa;
    	if(!p)t[np].fa=1;
    	else
    	{
    		int q=t[p].nxt[c];
    		if(t[q].len==t[p].len+1)t[np].fa=q;
    		else
    		{
    			int nq=++tot;
    			memcpy(t[nq].nxt,t[q].nxt,sizeof t[q].nxt);
    			t[nq].fa=t[q].fa,t[nq].len=t[p].len+1;
    			t[q].fa=t[np].fa=nq;
    			while(p&&t[p].nxt[c]==q)t[p].nxt[c]=nq,p=t[p].fa;
    		}
    	}
    }
    
    struct SegmentTree{
    	int mx[maxn<<2];
    	inline void update(int i,int l,int r,int p,int x)
    	{
    		if(l==r){mx[i]=x;return;}
    		int mid=(l+r)>>1;
    		if(p<=mid)update(i<<1,l,mid,p,x);
    		else update(i<<1|1,mid+1,r,p,x);
    		mx[i]=max(mx[i<<1],mx[i<<1|1]);
    	}
    	inline int getmx(int i,int l,int r,int ql,int qr)
    	{
    		if(qr<l||r<ql)return -INF;
    		if(ql<=l&&r<=qr)return mx[i];
    		int mid=(l+r)>>1;
    		return max(getmx(i<<1,l,mid,ql,qr),getmx(i<<1|1,mid+1,r,ql,qr));
    	}
    }T1,T2;
    
    int main()
    {
    	scanf("%s%s",S+1,T+1);lst=tot=1;
    	n=strlen(T+1);
    	for(int i=1;i<=n;i++)ins(T[i]-97);
    	n=strlen(S+1);int r=0,p=1;
    	for(int i=1;i<=n;i++)
    	{
    		r=max(i-1,r);
    		if(r==i-1)p=1;
    		while(p!=1&&t[t[p].fa].len+1>r-i+1)p=t[p].fa;
    		while(r<n&&t[p].nxt[S[r+1]-97])p=t[p].nxt[S[++r]-97];
    		q[++cnt]=(node){i,r,0,0};
    	}
    	for(int i=1;i<=n;i++)T1.update(1,1,n,i,-INF),T2.update(1,1,n,i,-i);
    	int m=getint();
    	for(int i=1;i<=m;i++)
    	{
    		int l=getint(),r=getint();
    		q[++cnt]=(node){l,r,1,i};
    	}
    	sort(q+1,q+cnt+1,cmp);
    	for(int i=1;i<=cnt;i++)
    		if(!q[i].op)
    		{
    			T1.update(1,1,n,q[i].l,q[i].r-q[i].l+1);
    			T2.update(1,1,n,q[i].l,-INF);
    		}
    		else ans[q[i].id]=max(T1.getmx(1,1,n,q[i].l,q[i].r),q[i].r+T2.getmx(1,1,n,q[i].l,q[i].r)+1);
    	for(int i=1;i<=m;i++)printf("%d
    ",ans[i]);
    }
    

  • 相关阅读:
    PyQt(Python+Qt)学习随笔:containers容器类部件QStackedWidget重要方法介绍
    什么叫工业4.0,这篇接地气的文章终于讲懂了
    怎样 真正认识一个 人
    华为的绩效管理:减人、增 效、加薪
    羽毛球战术
    魔方教程
    员工培养:事前指导,事后纠正
    一把手瞄准哪里,核心竞争力就在哪里
    海尔的五次战略变革
    如何提高基层员工的执行力
  • 原文地址:https://www.cnblogs.com/Darknesses/p/13259456.html
Copyright © 2011-2022 走看看