题解 [CF590E] Birthday

传送门

首先……怎么找出所有串之间的包含关系呢?
这个人太弱了只会根号找
所以当他赛后听说用 AC 自动机可以 \(O(\sum len)\) 的时候整个人傻掉了(

考虑对 AC 自动机上每个节点维护从这个点向上跳能跳到的第一个结束节点
然后这个东西可以在建 AC 自动机的时候处理出来
于是可以建立偏序关系
然后再跑一个传递闭包就可以建出完整的图了
然后就是 Dilworth 定理输出方案了,与 [CTSC2008]祭祀 是相同的
复杂度 \(O(m)\)

点击查看代码
#include <bits/stdc++.h>
using namespace std;	
#define INF 0x3f3f3f3f
#define N 1510
#define M 10000010
#define pb push_back
#define ll long long
#define ull unsigned long long
//#define int long long

int n;
string s[N];
// ull pw[10000010];
// const ull base=13131;
int uni[N], usiz, sum, max_len;

// namespace force{
// 	ull h[N];
// 	int ans, rec;
// 	unordered_map<ull, bool> mp;
// 	inline ull hashing(int l, int r) {return h[r]-h[l-1]*pw[r-l+1];}
// 	void solve() {
// 		int lim=1<<n;
// 		for (int s=0; s<lim; ++s) {
// 			mp.clear();
// 			for (int i=1; i<=n; ++i) if (s&(1<<i-1)) {
// 				ull h=0;
// 				for (auto it:(::s[i])) h=h*base+it;
// 				// if (s==7) cout<<"add: "<<i<<' '<<h<<endl;
// 				mp[h]=1;
// 			}
// 			for (int i=1; i<=n; ++i) if (s&(1<<i-1)) {
// 				// if (s==7) cout<<"i: "<<i<<endl;
// 				for (int j=1; j<=::s[i].length(); ++j) h[j]=h[j-1]*base+::s[i][j-1];
// 				for (int l=1; l<=::s[i].length(); ++l)
// 					for (int r=l; r<=::s[i].length(); ++r)
// 						if (!(l==1&&r==::s[i].length()) && mp.find(hashing(l, r))!=mp.end())
// 							goto jump;
// 			}
// 			if (__builtin_popcount(s)>ans) ans=__builtin_popcount(s), rec=s;
// 			jump: ;
// 		}
// 		cout<<ans<<endl;
// 		for (int i=1; i<=n; ++i) if (rec&(1<<i-1)) cout<<i<<' '; cout<<endl;
// 	}
// }

// namespace task1{
// 	ull h[10000010];
// 	vector<int> to[N];
// 	bool vis[1010][1010];
// 	unordered_map<ull, int> mp;
// 	int head[N], dep[N], cur[N], sta[N], ecnt=1, s, t, tot, ans, top;
// 	struct edge{int to, next, val;}e[N<<1];
// 	inline void add(int s, int t, int w) {e[++ecnt]={t, head[s], w}; head[s]=ecnt;}
// 	inline ull hashing(int l, int r) {return h[r]-h[l-1]*pw[r-l+1];}
// 	void build() {
// 		for (int i=1; i<=n; ++i) {
// 			ull h=0;
// 			for (auto it:(::s[i])) h=h*base+it;
// 			mp[h]=i;
// 		}
// 		for (int i=1,len; i<=n; ++i) {
// 			len=::s[i].length();
// 			for (int j=1; j<=len; ++j) h[j]=h[j-1]*base+::s[i][j-1];
// 			for (int j=1; j<=usiz; ++j) if (uni[j]<len) {
// 				for (int l=1; l+uni[j]-1<=len; ++l) {
// 					ull tem=hashing(l, l+uni[j]-1);
// 					if (mp.find(tem)!=mp.end() && !vis[i][mp[tem]]) to[i].pb(mp[tem]), vis[i][mp[tem]]=1; //, cout<<"link: "<<i<<' '<<mp[tem]<<endl;
// 				}
// 			}
// 		}
// 	}
// 	bool bfs(int s, int t) {
// 		for (int i=1; i<=tot; ++i) dep[i]=0;
// 		queue<int> q;
// 		dep[s]=1; cur[s]=head[s];
// 		q.push(s);
// 		while (q.size()) {
// 			int u=q.front(); q.pop();
// 			for (int i=head[u],v; ~i; i=e[i].next) {
// 				v = e[i].to;
// 				if (e[i].val&&!dep[v]) {
// 					dep[v]=dep[u]+1;
// 					cur[v]=head[v];
// 					if (v==t) return 1;
// 					q.push(v);
// 				}
// 			}
// 		}
// 		return 0;
// 	}
// 	int dfs(int u, int in) {
// 		if (u==t||!in) return in;
// 		int rest=in, tem;
// 		for (int i=cur[u],v; ~i; cur[u]=i=e[i].next) {
// 			v = e[i].to;
// 			if (e[i].val&&dep[v]==dep[u]+1) {
// 				tem=dfs(v, min(rest, e[i].val));
// 				if (!tem) dep[v]=0;
// 				rest-=tem;
// 				e[i].val-=tem;
// 				e[i^1].val+=tem;
// 				if (!rest) break;
// 			}
// 		}
// 		return in-rest;
// 	}
// 	void force_solve() {
// 		int lim=1<<n, ans=0, rec=0;
// 		bool vis[25];
// 		for (int s=0; s<lim; ++s) {
// 			for (int i=1; i<=n; ++i)
// 				if (s&(1<<i-1)) vis[i]=1;
// 				else vis[i]=0;
// 			for (int i=1; i<=n; ++i) if (s&(1<<i-1))
// 				for (auto v:to[i]) if (vis[v]) goto jump;
// 			if (__builtin_popcount(s)>ans) ans=__builtin_popcount(s), rec=s;
// 			jump: ;
// 		}
// 		cout<<ans<<endl;
// 		for (int i=1; i<=n; ++i) if (rec&(1<<i-1)) cout<<i<<' '; cout<<endl;
// 		exit(0);
// 	}
// 	void solve() {
// 		build();
// 		if (n<=20) force_solve();
// 		memset(head, -1, sizeof(head));
// 		s=2*n+1, t=2*n+2, tot=2*n+2;
// 		for (int u=1; u<=n; ++u)
// 			for (auto v:to[u])
// 				add(u, v+n, 1), add(v+n, u, 0);
// 		for (int i=1; i<=n; ++i) {
// 			add(s, i, 1), add(i, s, 0);
// 			add(i+n, t, 1), add(t, i+n, 0);
// 		}
// 		while (bfs(s, t)) ans+=dfs(s, INF);
// 		printf("%d\n", n-ans);
// 		for (int u=n+1; u<=2*n; ++u)
// 			for (int i=head[u],v; ~i; i=e[i].next)
// 				if (e[i].to==t&&e[i].val)
// 					sta[++top]=u-n;
// 		sort(sta+1, sta+top+1);
// 		for (int i=1; i<=top; ++i) for (int j=1; j<=top; ++j) if (vis[sta[i]][sta[j]]) goto jump;
// 		for (int i=1; i<=top; ++i) printf("%d%c", sta[i], " \n"[i==top]);
// 		return ; jump: top=0;
// 		for (int i=head[s],v; ~i; i=e[i].next) if (e[i].val) sta[++top]=e[i].to;
// 		sort(sta+1, sta+top+1);
// 		for (int i=1; i<=top; ++i) printf("%d%c", sta[i], " \n"[i==top]);
// 	}
// }

namespace task{
	bool vis[N];
	queue<int> q;
	bitset<N> mask[N];
	vector<int> to[N], sta;
	int tr[M][2], fail[M], top[M], tot;
	int head[N], dep[N], cur[N], ecnt=1, s, t, ans;
	struct edge{int to, next, val;}e[N*N*2];
	inline void add(int s, int t, int w) {e[++ecnt]={t, head[s], w}; head[s]=ecnt;}
	void ins(string& s, int id) {
		for (int p=0,*t,i=0; ; p=*t,++i) {
			t=&tr[p][s[i]-'a'];
			if (!*t) *t=++tot;
			if (i+1==s.length()) {top[*t]=id; return ;}
		}
	}
	void build() {
		for (int i=1; i<=n; ++i) ins(::s[i], i);
		int u=0;
		for (int i=0; i<2; ++i)
			if (tr[u][i]) fail[tr[u][i]]=u, q.push(tr[u][i]);
			else tr[u][i]=u;
		while (q.size()) {
			u=q.front(); q.pop();
			for (int i=0; i<2; ++i)
				if (tr[u][i]) {
					fail[tr[u][i]]=tr[fail[u]][i], q.push(tr[u][i]);
					if (!top[tr[u][i]]) top[tr[u][i]]=top[fail[tr[u][i]]];
				}
				else tr[u][i]=tr[fail[u]][i];
		}
		for (int i=1; i<=n; ++i) {
			// cout<<"i: "<<i<<endl;
			for (int p=0,j=0; ; p=tr[p][::s[i][j++]-'a']) {
				// cout<<"j: "<<j<<' '<<top[p]<<endl;
				if (top[p]&&top[p]!=i) mask[i][top[p]]=1;
				if (j==::s[i].length()) {
					if (top[fail[p]]) mask[i][top[fail[p]]]=1;
					break;
				}
			}
		}
		// cout<<"---e---"<<endl; for (int i=1; i<=n; ++i) {for (int j=1; j<=n; ++j) cout<<mask[i][j]<<' '; cout<<endl;}
		for (int k=1; k<=n; ++k)
			for (int i=1; i<=n; ++i) if (mask[i][k])
				mask[i]|=mask[k];
		for (int i=1; i<=n; ++i)
			for (int j=1; j<=n; ++j) if (mask[i][j])
				to[i].pb(j); //, cout<<"link: "<<i<<' '<<j<<endl;
	}
	bool bfs(int s, int t) {
		for (int i=1; i<=tot; ++i) dep[i]=0;
		queue<int> q;
		dep[s]=1; cur[s]=head[s];
		q.push(s);
		while (q.size()) {
			int u=q.front(); q.pop();
			for (int i=head[u],v; ~i; i=e[i].next) {
				v = e[i].to;
				if (e[i].val&&!dep[v]) {
					dep[v]=dep[u]+1;
					cur[v]=head[v];
					if (v==t) return 1;
					q.push(v);
				}
			}
		}
		return 0;
	}
	int dfs(int u, int in) {
		if (u==t||!in) return in;
		int rest=in, tem;
		for (int i=cur[u],v; ~i; cur[u]=i=e[i].next) {
			v = e[i].to;
			if (e[i].val&&dep[v]==dep[u]+1) {
				tem=dfs(v, min(rest, e[i].val));
				if (!tem) dep[v]=0;
				rest-=tem;
				e[i].val-=tem;
				e[i^1].val+=tem;
				if (!rest) break;
			}
		}
		return in-rest;
	}
	void dfs(int u) {
		vis[u]=1;
		for (int i=head[u],v; ~i; i=e[i].next) {
			v = e[i].to;
			if (v!=s&&v!=t&&!e[i].val&&!vis[v]) dfs(v);
		}
	}
	void solve() {
		build();
		memset(head, -1, sizeof(head));
		s=2*n+1, t=2*n+2, tot=2*n+2;
		for (int u=1; u<=n; ++u)
			for (auto v:to[u])
				add(u, v+n, 1), add(v+n, u, 0);
		for (int i=1; i<=n; ++i) {
			add(s, i, 1), add(i, s, 0);
			add(i+n, t, 1), add(t, i+n, 0);
		}
		while (bfs(s, t)) ans+=dfs(s, INF);
		printf("%d\n", n-ans);
		for (int u=n+1; u<=2*n; ++u)
			for (int i=head[u],v; ~i; i=e[i].next)
				if (e[i].to==t && e[i].val)
					dfs(u);
		for (int i=1; i<=n; ++i) if (!(vis[i]||!vis[i+n])) sta.pb(i);
		sort(sta.begin(), sta.end());
		for (auto it:sta) printf("%d ", it);
		printf("\n");
	}
}

signed main()
{
	freopen("a.in", "r", stdin);
	freopen("a.out", "w", stdout);
	ios::sync_with_stdio(0);

	cin>>n;
	for (int i=1; i<=n; ++i) {
		cin>>s[i];
		// max_len=max(max_len, (int)s[i].length());
		// sum+=(uni[++usiz]=s[i].length());
	}
	// pw[0]=1;
	// for (int i=1; i<=max_len; ++i) pw[i]=pw[i-1]*base;
	// sort(uni+1, uni+usiz+1);
	// usiz=unique(uni+1, uni+usiz+1)-uni-1;
	// force::solve();
	task::solve();

	return 0;
}
posted @ 2022-06-13 17:45  Administrator-09  阅读(1)  评论(0编辑  收藏  举报