zoukankan      html  css  js  c++  java
  • LOJ3049 「十二省联考 2019」字符串问题

    题目传送门

    分析:
    最暴力的做法,A向可以控制的B连边,B向以它为前缀的A连边
    然后拓扑排序求一条路径的最大值
    复杂度(O(n^2))
    明显要优化连边,这里给出两种解法:

    SAM优化建边:
    这里要前缀关系,我们反向建SAM将其变成后缀关系
    对于每个串([l,r]),我们先找到(r)结尾的前缀在SAM上的位置,通过Parent树上倍增找到([l,r])所在的endpos集合的点
    对于每个Parent树上的点,维护一个vector,保存在这个点上的A和B
    同一个点上的A和B,先按len为关键字从小到大排序,再将B优先放前面,A优先放后面
    每个点向它子串集合中最短的连边,B向比他长的并且比下一个B短的A连边,Parent树父亲集合中最长的串向儿子连边
    再把控制关系连上去
    然后直接跑拓扑排序,时空复杂度都会从(O(n^2))变成(O(n))
    写起来细节挺多的有点恶心

    后缀数组+主席树优化建边:
    我们先用原串跑一次后缀数组
    B是A的前缀只需要(min_{i=rk[lB]+1}^{rk[lA]}height[i]geq len[B])
    我们对于每个B,满足上述关系的一定是一个包含(lB)的区间
    这个可以二分+(O(1))RMQ解决
    然后线段树优化建边?不行
    发现A的长度如果小于B就会出现问题
    那就用主席树
    把子串长度从大到小排序,一个一个加入再优化建边就可以了
    然后把控制关系也加进去
    跑拓扑排序,但是时空复杂度都是(O(nlogn)),很卡常

    代码是第一种做法的:
    (后缀数组是个好东西,我有头发的时候天天写)

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    #include<queue>
    #include<map>
    
    #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,m,na,nb;
    int fir[maxn<<2],nxt[maxn<<3],to[maxn<<3],cnt;
    struct node{
    	int fa,nxt[26],len;
    }t[maxn];
    int lst,tot,cur;
    char s[maxn];
    int len[maxn<<2],Ed[maxn<<2],pos[maxn<<2];
    int Id[maxn<<2],f[maxn][20],In[maxn<<2];
    int A[maxn<<2],B[maxn<<2];
    long long F[maxn<<2];
    vector<int>g[maxn<<2];
    inline bool cmp(int x,int y){return len[x]==len[y]?pos[x]<pos[y]:len[x]<len[y];}
    
    inline void insert(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;
    		}
    	}
    }
    inline void solve(int val)
    {
    	int l=getint(),r=getint();
    	r=r-l+1,l=Id[l];
    	for(int j=19;~j;j--)if(f[l][j]&&t[f[l][j]].len>=r)l=f[l][j];
    	pos[++cur]=val,len[cur]=r,g[l].push_back(cur);
    }
    inline void newnode(int u,int v)
    {to[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt,In[v]++;}
    inline void toposort()
    {
    	queue<int>Q;
    	for(int i=1;i<=cur;i++){F[i]=len[i];if(!In[i])Q.push(i);}
    	while(!Q.empty())
    	{
    		int u=Q.front();Q.pop();
    		for(int i=fir[u];i;i=nxt[i])
    		{
    			F[to[i]]=max(F[to[i]],F[u]+len[to[i]]);
    			if(!(--In[to[i]]))Q.push(to[i]);
    		}
    	}
    }
    
    int main()
    {
    	int T=getint();
    	while(T--)
    	{
    		lst=tot=1;
    		memset(t,0,sizeof t);
    		memset(fir,0,sizeof fir),cnt=0;
    		memset(In,0,sizeof In),memset(pos,0,sizeof pos);
    		scanf("%s",s+1);n=strlen(s+1);
    		for(int i=n;i;i--)insert(s[i]-'a'),Id[i]=lst;
    		for(int i=1;i<=tot;i++)f[i][0]=t[i].fa;
    		for(int j=1;j<20;j++)for(int i=1;i<=tot;i++)f[i][j]=f[f[i][j-1]][j-1];
    		na=getint();cur=tot;
    		for(int i=1;i<=na;i++)solve(1),A[i]=cur;
    		nb=getint();
    		for(int i=1;i<=nb;i++)solve(0),B[i]=cur;
    		for(int i=1;i<=tot;i++)
    		{
    			sort(g[i].begin(),g[i].end(),cmp);
    			int pre=i;
    			for(int j=0;j<g[i].size();j++)
    			{
    				newnode(pre,g[i][j]);
    				if(!pos[g[i][j]])pre=g[i][j];
    			}
    			Ed[i]=pre;
    		}
    		for(int i=1;i<=tot;i++)g[i].clear();
    		for(int i=2;i<=tot;i++)newnode(Ed[t[i].fa],i);
    		for(int i=1;i<=cur;i++)if(!pos[i])len[i]=0;
    		m=getint();
    		for(int i=1;i<=m;i++)
    		{
    			int u=getint(),v=getint();
    			newnode(A[u],B[v]);
    		}
    		toposort();
    		bool flg=0;
    		for(int i=1;i<=cur;i++)if(In[i]){flg=1;break;}
    		if(flg)printf("-1
    ");
    		else printf("%lld
    ",*max_element(F+1,F+cur+1));
    	}
    }
    

  • 相关阅读:
    轻量级的Web服务器Nginx0.9.0 开发版发布 狼人:
    微软发布Silverlight 5 Beta新特性 狼人:
    TechCrunch新闻评论:Flash耗电问题严重 狼人:
    IE9是最佳浏览器? 狼人:
    Silverlight面向客户端,HTML5面向Web 狼人:
    Silverlight 结构分析 狼人:
    HTML5是否已经准备好了?仍在W3C层层审核当中 狼人:
    Adobe驳斥Flash过度耗电论 称HTML5更耗电 狼人:
    Silverlight 5即将来临 狼人:
    运行控制[置顶] 有趣的编程控制自己电脑的CPU
  • 原文地址:https://www.cnblogs.com/Darknesses/p/13095657.html
Copyright © 2011-2022 走看看