zoukankan      html  css  js  c++  java
  • 「BalticOI 2020」病毒

    「BalticOI 2020」病毒

    设点集大小为(N),边集总长度(sum k=M),模板串总长(L=sum ℓ)

    涉及到多串匹配的转移问题,容易想到( ext{AC})自动机

    因为本题状态非常少,可以暴力矩阵维护转移,暴力计算由状态(i)转移至状态(j),且中途不匹配的最小长度

    (NL^2)个状态

    给定的是一张有向图,可以用奇怪的( ext{Bellman-Ford,Dijkstra})完成暴力转移

    复杂度未知。。。上界应该比较高,但是鉴于常数小可以通过

    [ ]

    [ ]

    优化的转移:把每一条边的前缀拆出来,建立虚点

    这样以来,所有状态转移可以归纳为 虚点+实点 ( o) 虚点/实点

    一共有((N+M)L^2)个状态,((N+M)L^2)种转移,每种转移涉及两个元素,产生(L)个元素

    故对于每种转移的每一方,被遍历时都要枚举依次转移,共有(2(N+M)L^3)次转移

    因此可以认为建立的图有((N+M)L^2)个点,(2(N+M)L^3)条边

    对此运行 类似 最短路算法即可

    因此用( ext{Dijkstra})维护转移的复杂度为(O( (N+M)L^3 log ((N+M)L^2) ))

    [ ]

    ---以下是未优化Bellman-Ford代码----

    #include<bits/stdc++.h>
    using namespace std;
    typedef unsigned long long ll;
    #define pb push_back
    #define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
    #define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
    template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
    template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); }
    
    char IO;
    template <class T=int> T rd(){
    	T s=0; int f=0;
    	while(!isdigit(IO=getchar())) f|=IO=='-';
    	do s=(s<<1)+(s<<3)+(IO^'0');
    	while(isdigit(IO=getchar()));
    	return f?-s:s;
    }
    
    const int N=110,M=54;
    
    
    int n,m,k;
    typedef vector <int> V;
    int trie[M][2],fail[M],mk[M],cnt;
    void Ins(const V &S){
    	int now=0;
    	for(int i:S) {
    		int &nxt=trie[now][i];
    		if(!nxt) nxt=++cnt;
    		now=nxt;
    	}
    	mk[now]=1;
    }
    void Build(){
    	static queue <int> que;
    	rep(i,0,1) if(trie[0][i]) que.push(trie[0][i]);
    	while(!que.empty()) { 
    		int u=que.front(); que.pop();
    		mk[u]|=mk[fail[u]];
    		rep(i,0,1){
    			int &v=trie[u][i];
    			if(v) que.push(v);
    			(!v?v:fail[v])=trie[fail[u]][i];
    		}
    	}
        // delete illegal state
    	rep(i,0,cnt) rep(j,0,1) if(mk[trie[i][j]]) trie[i][j]=cnt+1;
    }
    
    V Read(){
    	V Res;
    	rep(i,1,rd()) Res.pb(rd());
    	return Res;
    }
    
    vector <V> G[N];
    int E[N][N];
    const ll INF=-1;
    ll dis[N][M][M],ans[N];
    int fl=1;
    void Work(int u){
    	static ll F[M][M],G[M][M];
    	ll f=INF;
    	for(V S:(::G[u])) {
    		memset(F,255,sizeof F);
    		rep(i,0,cnt) F[i][i]=0;
    		for(int c:S) {
    			rep(i,0,cnt) rep(j,0,cnt) G[i][j]=F[i][j],F[i][j]=INF;
    			rep(i,0,cnt) rep(j,0,cnt) if(G[i][j]<INF) 
    				rep(k,0,cnt) if(G[i][j]+dis[c][j][k]>=max(G[i][j],dis[c][j][k])) 
    					cmin(F[i][k],G[i][j]+dis[c][j][k]);
    		}
    		rep(i,0,cnt) rep(j,0,cnt) if(dis[u][i][j]>F[i][j]) dis[u][i][j]=F[i][j],cmin(f,F[i][j]);
    	}
    	if(f!=INF) fl=1;
    }
    
    int main(){
    	n=rd()-1,m=rd(),k=rd();
    	rep(i,1,m) {
    		int u=rd(); V w=Read();
    		G[u].pb(w);
    		for(int v:w) E[v][u]=1;
    	}
    	rep(i,1,k) Ins(Read());
    	Build();
    	memset(dis,255,sizeof dis),memset(ans,255,sizeof ans);
    	rep(u,0,1) rep(i,0,cnt) if(!mk[i]) dis[u][i][trie[i][u]]=1;
    	while(fl){
    		fl=0;
    		rep(i,2,n) Work(i);
    	}
    	rep(i,2,n) rep(j,0,cnt) if(!mk[j]) cmin(ans[i],dis[i][0][j]);
    	rep(i,2,n) {
    		if(ans[i]==INF) puts("YES");
    		else printf("NO %llu
    ",ans[i]);
    	}
    }
    

    ----以下是无比垃圾的优化代码----

    #include<bits/stdc++.h>
    using namespace std;
    typedef unsigned long long ll;
    #define pb push_back
    typedef pair <int,int> Pii;
    #define mp make_pair
    #define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
    #define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
    char IO;
    int rd(){
    	int s=0;
    	while(!isdigit(IO=getchar()));
    	do s=(s<<1)+(s<<3)+(IO^'0');
    	while(isdigit(IO=getchar()));
    	return s;
    }
    
    const int N=210,M=52;
    const ll INF=-1;
    
    int n,m,k,c;
    typedef vector <int> V;
    int trie[M][2],fail[M],mk[M],cnt;
    void Ins(const V &S){
    	int now=0;
    	for(int i:S) {
    		int &nxt=trie[now][i];
    		if(!nxt) nxt=++cnt;
    		now=nxt;
    	}
    	mk[now]=1;
    }
    void Build(){
    	static queue <int> que;
    	rep(i,0,1) if(trie[0][i]) que.push(trie[0][i]);
    	while(!que.empty()) { 
    		int u=que.front(); que.pop();
    		mk[u]|=mk[fail[u]];
    		rep(i,0,1){
    			int &v=trie[u][i];
    			if(v) que.push(v);
    			(!v?v:fail[v])=trie[fail[u]][i];
    		}
    	}
    	mk[cnt+1]=1;
    	rep(i,0,cnt) rep(j,0,1) if(mk[i] || mk[trie[i][j]]) trie[i][j]=cnt+1;
    }
    
    V Read(){
    	V Res;
    	rep(i,1,rd()) Res.pb(rd());
    	return Res;
    }
    
    vector <Pii> G[N];
    ll dis[N][M][M];
    struct Node{
    	int u,s,t;
    	ll d;
    	bool operator < (const Node &__) const {
    		return d>__.d;
    	}
    };
    priority_queue <Node> que;
    void Upd(int u,int s,int t,ll d){
    	if(mk[s]||mk[t]||dis[u][s][t]<=d) return;
    	dis[u][s][t]=d,que.push((Node){u,s,t,d});
    }
    
    int main(){
    	c=n=rd()-1,m=rd(),k=rd();
    	++c; // 建立一个空虚点
    	rep(i,1,m) {
    		int u=rd(); V w=Read();
    		int lst=n+1;
    		rep(j,0,w.size()-1) {
    			if(j==jend) G[lst].pb(mp(w[j],u)),G[w[j]].pb(mp(lst,u));
    			else G[lst].pb(mp(w[j],++c)),G[w[j]].pb(mp(lst,c)),lst=c;
    		}
    	}
    	rep(i,1,k) Ins(Read());
    	Build();
    	memset(dis,255,sizeof dis);
    	rep(i,0,cnt) if(!mk[i]) dis[n+1][i][i]=0; // 单位矩阵
    	rep(u,0,1) rep(i,0,cnt) Upd(u,i,trie[i][u],1);
    	while(!que.empty()) {
    		int u=que.top().u,s=que.top().s,t=que.top().t;
    		ll d=que.top().d;  que.pop();
    		if(d>dis[u][s][t]) continue;
    		for(auto i:G[u]) {
    			int v=i.first,to=i.second;
    			if(u<=n) {
    				rep(i,0,cnt) if(dis[v][i][s]<INF) Upd(to,i,t,dis[v][i][s]+d);
    			} else {
    				rep(i,0,cnt) if(dis[v][t][i]<INF) Upd(to,s,i,d+dis[v][t][i]);
    			}
    		}
    	}
    	rep(i,2,n) {
    		ll ans=-1;
    		rep(j,0,cnt) if(!mk[j]) ans=min(ans,dis[i][0][j]);
    		if(ans==INF) puts("YES");
    		else printf("NO %llu
    ",ans);
    	}
    }
    
  • 相关阅读:
    类对象成员函数的const增强zz
    希腊与罗马神话神名对照
    c++程序调用c函数 and otherwise zz
    百度相信中国电子书下载
    VolatileCorrectness,让编译器帮你检测竞争条件 zz
    高效计算一个bytes有几个byte是1?
    实现mybatis官网入门实例
    Windows Phone 深度探索(一) 带有(伪)元素加载动画的Panel (SlideInPanel)
    You have asked for this, it is basically your fault!
    New EC2 Instance Types of re:Invent 2021
  • 原文地址:https://www.cnblogs.com/chasedeath/p/14508484.html
Copyright © 2011-2022 走看看