Solution
将所有串放到trie树上,每个点记录一个状态表示它可以作为哪些串的结尾
bfs搜索字典序最小的包含所有串结尾的母串
Code
#include <cstdio> #include <cstdlib> #include <queue> using namespace std; const int N=610,M=1<<12; int L1[N*M],L2[N*M],head,tail,ans[N],S=1,fa[N],n,tot=1,trie[N][26],fail[N],state[N],id[N]; bool flag[N][M]; char s[51]; queue <int> q; struct node { int u,f; }; queue <node> Q; void add(int pos) { int now=S; for(int i=0;s[i];i++) { int wh=s[i]-'A'; if(!trie[now][wh]) trie[now][wh]=++tot; now=trie[now][wh]; } state[now]|=(1<<pos); } void get_fail() { for(int i=0;i<26;i++) if(trie[S][i]) q.push(trie[S][i]),fail[trie[S][i]]=S; else trie[S][i]=S; while(!q.empty()) { int u=q.front(); q.pop(); state[u]|=state[fail[u]]; for(int i=0;i<26;i++) { int v=trie[u][i]; if(v) q.push(v),fail[v]=trie[fail[u]][i]; else trie[u][i]=trie[fail[u]][i]; } } } void solve() { head=tail=1; Q.push((node){1,0}); flag[1][0]=1; while(head<=tail) { node t=Q.front(); Q.pop(); if(t.f==(1<<n)-1) { int num=0; for(;head>1;head=L2[head]){ans[++num]=L1[head];} for(int i=num;i;i--) printf("%c",ans[i]+'A'); return; } for(int i=0;i<26;i++) { int v=trie[t.u][i]; int k=t.f|state[trie[t.u][i]]; if(flag[v][k]) continue; L1[++tail]=i; L2[tail]=head; flag[v][k]=1; Q.push((node){v,k}); } head++; } } int main() { scanf("%d",&n); for(int i=0;i<n;i++) scanf("%s",s),add(i); get_fail(); solve(); return 0; }