【Codeforces 590 E】Birthday(AC自动机 / 二分图匹配)

传送门

建出 A c Ac 自动机后即可求出串和串之间的偏序关系
建成一个 D A G DAG
然后做一次最长反链并输出方案即可

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define y1 shinkle
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob)?EOF:*ib++;
}
inline int read(){
    char ch=gc();
    int res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline ll readll(){
    char ch=gc();
    ll res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline int readstring(char *s){
	int top=0;char ch=gc();
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
	s[top+1]='\0';return top;
}
inline void reads(vector<char>&s){
	char ch=gc();
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s.pb(ch),ch=gc();
}
template<typename tp>inline void chemx(tp &a,tp b){a=max(a,b);}
template<typename tp>inline void chemn(tp &a,tp b){a=min(a,b);}
cs int N=777,M=10000005;
vector<char>str[N];
int n;
bool lk[N][N];
inline void addedge(int u,int v){
	lk[u][v]=1;
}
namespace Ac{
	int nxt[M][2],fail[M],bel[M],tot;
	inline void insert(char *s,int l,int id){
		int p=0;
		for(int i=0;i<l;i++){
			int c=s[i]-'a';
			if(!nxt[p][c])nxt[p][c]=++tot;
			p=nxt[p][c];
		}bel[p]=id;
	}
	int q[M],hd,tl,up[M];
	bool vis[M];
	inline int find(int p){
		if(p==0)return -1;
		if(bel[p])return p;
		if(up[p])return up[p];
		return up[p]=find(fail[p]);
	}
	inline void buildfail(){
		hd=1;
		for(int i=0;i<2;i++){
			if(nxt[0][i])q[++tl]=nxt[0][i];
		}
		while(hd<=tl){
			int p=q[hd++];
			for(int c=0;c<2;c++){
				int v=nxt[p][c];
				if(!v)nxt[p][c]=nxt[fail[p]][c];
				else fail[v]=nxt[fail[p]][c],q[++tl]=v;
			}
		}
		q[hd=tl=1]=0;
		vis[0]=1;
		while(hd<=tl){
			int p=q[hd++];
			up[p]=find(fail[p]);
			for(int c=0;c<2;c++)if(!vis[nxt[p][c]]){
				int v=nxt[p][c];vis[v]=1,q[++tl]=v;
			}
		}
	}
	inline void getlk(char *s,int l,int id){
		int p=0;
		for(int i=0;i<l;i++){
			int c=s[i]-'a';
			p=nxt[p][c];
			int t=bel[p]?p:up[p];
			while(t!=-1&&bel[t]==id)t=up[t];
			if(t!=-1)addedge(id,bel[t]);
		}
	}
}
inline void Floyd(){
	for(int k=1;k<=n;k++)
	for(int i=1;i<=n;i++)if(k!=i)
	for(int j=1;j<=n;j++)if(j!=i&&j!=k)
	lk[i][j]|=lk[i][k]&lk[k][j];
}
int mat[N*2],vis[N*2];
vector<int> e[N*2];
int vl[N*2],vr[N*2];
void find(int u){
	if(vr[u])return;
	vr[u]=1;
	for(int &v:e[u])if(v!=mat[u]){
		if(!vl[v])vl[v]=1,find(mat[v]);
	}
}
bool dfs(int u){
	if(vis[u])return false;
	vis[u]=1;
	for(int v:e[u])if(!mat[v]||dfs(mat[v])){
		mat[v]=u,mat[u]=v;return true;
	}return false;
}
int main(){
	#ifdef Stargazer
	freopen("lx.in","r",stdin);
	#endif
	n=read();
	for(int i=1;i<=n;i++){
		reads(str[i]);
		Ac::insert(&str[i][0],str[i].size(),i);
	}Ac::buildfail();
	for(int i=1;i<=n;i++)
		Ac::getlk(&str[i][0],str[i].size(),i);
	Floyd();
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)if(i!=j&&lk[i][j])
	e[i].pb(j+n),e[j+n].pb(i);
	int res=n;
	for(int i=1;i<=n;i++)if(!mat[i])memset(vis,0,sizeof(vis)),res-=dfs(i);
	cout<<res<<'\n';
	for(int i=1;i<=n;i++)if(!mat[i+n])find(i+n);
	for(int i=1;i<=n;i++)if(!vl[i]&&vr[i+n])cout<<i<<" ";
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42555009/article/details/105702789