HNOI2006 最短母串问题

传送门

A C AC AC自动机上 b f s bfs bfs即可。用 v i s [ i d ] [ s t a t e ] vis[id][state] vis[id][state]表示当前处于 A C AC AC自动机上 i d id id号节点,已包含串的状态为 s t a t e state state。由于是 b f s bfs bfs,所以可以保证第一次搜到的即为最短的。搜到包含所有串的状态输出即可。
要把一个节点的 f a i l fail fail的贡献加到该节点身上。

#include
#define cs const
#define re register
#define pii pair
#define mp make_pair
#define fi first
#define se second
using namespace std;
cs int N=12,L=51,alpha=26;
int n,tot=0;char s[L];
struct node{int son[alpha],fail,val;}a[N*L];
inline void insert(char *s,int id){
	int now=0,len=strlen(s);
	for(int re i=0;i<len;++i){
		if(!a[now].son[s[i]-'A'])
			a[now].son[s[i]-'A']=++tot;
		now=a[now].son[s[i]-'A'];
	}a[now].val|=(1<<(id-1));
}
inline void build_fail(){
	queue<int> Q;
	for(int i=0,v;i<alpha;++i)
		if(v=a[0].son[i]) Q.push(v),a[v].fail=0;
	while(!Q.empty()){
		int u=Q.front();Q.pop();
		a[u].val|=a[a[u].fail].val;
		for(int re i=0,v;i<alpha;++i)
			if(v=a[u].son[i]) a[v].fail=a[a[u].fail].son[i],Q.push(v);
			else a[u].son[i]=a[a[u].fail].son[i];
	}
}
int S,ans[N*L][1<<N];
bool vis[N*L][1<<N];
pii pre[N*L][1<<N];
inline void print(cs pii &U){
	if(!(U.fi+U.se)) return;
	print(pre[U.fi][U.se]);
	putchar(ans[U.fi][U.se]+'A');
}
inline void bfs(){
	queue<pii> Q;Q.push(mp(0,0)),vis[0][0]=1;
	while(!Q.empty()){
		pii U=Q.front();Q.pop();
		int u=U.fi,s=U.se;
		if(s==S){print(U);puts("");return;}
		for(int i=0,v,t;i<alpha;++i){
			if(vis[v=a[u].son[i]][t=s|a[v].val]) continue;
			pre[v][t]=U,ans[v][t]=i,vis[v][t]=1,Q.push(mp(v,t));
		}
	}
}
int main(){
//	freopen("1980.in","r",stdin);
	scanf("%d",&n),S=(1<<n)-1;
	for(int i=1;i<=n;++i)
		scanf("%s",s),insert(s,i);
	build_fail(),bfs();
}

你可能感兴趣的:(HNOI2006 最短母串问题)