zoukankan      html  css  js  c++  java
  • P5284 [十二省联考2019]字符串问题

    题解

    这道题目也太重工业了吧。。。

    胡题 (20 min) ,写题 (5 days) ,还没写出来 ,我只能爪巴。

    不想调了,写篇题解记录一下思路。

    就是你给反串建出 ( ext{SAM}) 之后在考虑直接在树上建图,然后跑一个 ( ext{top}) 就可以了。

    代码

    (0pts) ,样例都过了,想调的人可以帮我调一下。

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int N=4e5+5;
    int ls,na,nb,m,id[N];char s[N];
    struct Sub{int l,r,len;}a[N],b[N];
    int tot=0,tag[N][2],f[N<<1],res;
    struct Tree{
    	struct Edge{int nxt,from,to;}e[N<<1];int fir[N<<1],deg[N<<1],size=0;
    	void add(int u,int v){e[++size]=(Edge){fir[u],u,v},deg[v]++,fir[u]=size;}
    }t1,t2;
    struct SAM{
    	int tot,lst;
    	struct Node{
    		int len,fa[20],go[26];
    		vector<pair<int,pair<int,int> > > bag;
    	}tr[N<<1];
    	void clear(){
    		tot=lst=1;
    		for(int i=0;i<(N<<1);++i){
    			tr[i].len=tr[i].fa[0]=0,tr[i].bag.clear();
    			memset(tr[i].go,0,sizeof(tr[i].go));
    		}
    	}
    	void insert(int x){
    		int u=lst,now=lst=++tot;
    		tr[now].len=tr[u].len+1;
    		while(u&&!tr[u].go[x])
    		tr[u].go[x]=now,u=tr[u].fa[0];
    		if(!u) return tr[now].fa[0]=1,void();
    		int v=tr[u].go[x];
    		if(tr[u].len+1==tr[v].len)
    		return tr[now].fa[0]=v,void();
    		int w=++tot;tr[w]=tr[v];
    		tr[w].len=tr[u].len+1;
    		tr[v].fa[0]=tr[now].fa[0]=w;
    		while(u&&tr[u].go[x]==v)
    		tr[u].go[x]=w,u=tr[u].fa[0];
    	}
    }sam;
    void dfs(int u,int anc){
    	sort(sam.tr[u].bag.begin(),sam.tr[u].bag.end());
    	for(int i=0;i<(int)sam.tr[u].bag.size();++i){
    		pair<int,pair<int,int> > tmp=sam.tr[u].bag[i];
    		if(i&&tmp.first==sam.tr[u].bag[i-1].first)
    		tag[tmp.second.first][tmp.second.second]=tot;
    		else{
    			tag[tmp.second.first][tmp.second.second]=++tot;
    			if(anc) t2.add(anc,tot),anc=tot;
    		}
    	}
    	for(int i=t1.fir[u];i;i=t1.e[i].nxt) dfs(t1.e[i].to,anc);
    }
    void init(){
    	tot=t1.size=t2.size=res=0;
    	memset(s,0,sizeof(s));
    	memset(tag,0,sizeof(tag));
    	memset(t1.fir,0,sizeof(t1.fir));
    	memset(t1.deg,0,sizeof(t1.deg));
    	memset(t2.fir,0,sizeof(t2.fir));
    	memset(t2.deg,0,sizeof(t2.deg));
    	for(int i=0;i<(N<<1);++i) f[i]=-1e18-7;
    	sam.clear();
    }
    bool top(){
    	queue<int> q;
    	f[tot+na+1]=0,q.push(tot+na+1);
    	for(int i=1;i<=tot+na;++i) if(!t2.deg[i]) q.push(i);
    	while(!q.empty()){
    		int u=q.front();q.pop();
    		res=max(res,f[u]);
    		// printf("%lld %lld
    ",u,f[u]);
    		for(int i=t2.fir[u];i;i=t2.e[i].nxt){
    			int v=t2.e[i].to;t2.deg[v]--;
    			if(v<=tot) f[v]=max(f[v],f[u]);
    			else f[v]=max(f[v],f[u]+a[v-tot].len);
    			if(!t2.deg[v]) q.push(v);
    		}
    	}
    	for(int i=1;i<=tot+na+1;++i) if(t2.deg[i]) return false;
    	return true;
    }
    void solve(){
    	scanf("%s",s+1),ls=strlen(s+1);
    	for(int i=ls;i>=1;--i){
    		sam.insert(s[i]-'a');
    		id[ls-i+1]=sam.tot;
    	}
    	for(int i=2;i<=sam.tot;++i){
    		t1.add(sam.tr[i].fa[0],i);
    	}
    	for(int j=1;j<20;++j){
    		for(int i=1;i<=sam.tot;++i)
    		sam.tr[i].fa[j]=sam.tr[sam.tr[i].fa[j-1]].fa[j-1];
    	}
    	scanf("%lld",&na);
    	for(int i=1;i<=na;++i){
    		scanf("%lld%lld",&a[i].r,&a[i].l);
    		a[i].l=ls-a[i].l+1,a[i].r=ls-a[i].r+1;
    		int u=id[a[i].r];a[i].len=a[i].r-a[i].l+1;
    		for(int j=19;j>=0;--j){
    			if(sam.tr[sam.tr[u].fa[j]].len>=a[i].len)
    			u=sam.tr[u].fa[j];
    		}
    		sam.tr[u].bag.push_back(make_pair(a[i].len,make_pair(i,0)));
    	}
    	scanf("%lld",&nb);
    	for(int i=1;i<=nb;++i){
    		scanf("%lld%lld",&b[i].r,&b[i].l);
    		b[i].l=ls-b[i].l+1,b[i].r=ls-b[i].r+1;
    		int u=id[b[i].r];b[i].len=b[i].r-b[i].l+1;
    		for(int j=19;j>=0;--j){
    			if(sam.tr[sam.tr[u].fa[j]].len>=b[i].len)
    			u=sam.tr[u].fa[j];
    		}
    		sam.tr[u].bag.push_back(make_pair(b[i].len,make_pair(i,1)));
    	}
    	dfs(1,0);
    	for(int i=1;i<=na;++i){
    		t2.add(tot+na+1,tot+i);
    		t2.add(tag[i][0],tot+i);
    	}
    	scanf("%lld",&m);
    	for(int i=1;i<=m;++i){
    		int u,v;scanf("%lld%lld",&u,&v);
    		t2.add(tot+u,tag[v][1]);
    	}
    	// for(int i=1;i<=t2.size;++i){
    	// 	printf("%lld %lld
    ",t2.e[i].from,t2.e[i].to);
    	// }
    	return printf("%lld
    ",top()?res:-1ll),void();
    }
    signed main(){
    	int T;cin>>T;
    	while(T--) init(),solve();
    }
    /*
    1
    abbaabbaab
    4
    1 5
    4 7
    6 9
    8 10
    3
    1 6
    10 10
    4 6
    5
    1 2
    1 3
    2 1
    3 3
    4 1
    */
    
  • 相关阅读:
    支付宝及时到帐接口使用详解
    Linux 天翼3G上网
    VBS常用函数及功能
    mencoder和ffmpeg参数详解
    C# 将数据导出到Excel汇总
    C# WinForm开发系列 Excel
    C#中的String.Format方法
    Google Maps API 代码
    ffmpeg的使用
    C# WinForm开发系列 Crystal Report
  • 原文地址:https://www.cnblogs.com/Point-King/p/14648167.html
Copyright © 2011-2022 走看看