Description
给定 (n le 12) 个字符串,要求找到一个最短的母串使得这 (n) 个字符串都是它的子串。如果有多个合法解则输出字典序最小的。每个字符串的长度不超过 (50)。
Solution
对 (n) 个字符串建立 AC 自动机,对于每个串的末尾结点,打上标记。
建自动机的时候记得把标记下传一下
然后跑 BFS 即可,记录下每个点的来源,然后倒序输出
BFS 的时候先从小边走,以保证字典序
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
int ch[N][26],fi[N],val[N],n,m,t1,t2,t3,t4,ind;
pair<short,short> from[N][5005];
char chr[N][5005],vis[N][5005];
void ins(char *s,int px) {
int len=strlen(s),p=0;
for(int i=0;i<len;i++) {
if(ch[p][s[i]-'A']==0) ch[p][s[i]-'A']=++ind;
p=ch[p][s[i]-'A'];
}
val[p]|=1<<px;
}
void build() {
queue <int> q;
for(int i=0;i<26;i++) if(ch[0][i]) q.push(ch[0][i]);
while(!q.empty()) {
int p=q.front(); q.pop();
for(int i=0;i<26;i++)
if(ch[p][i]) fi[ch[p][i]]=ch[fi[p]][i],q.push(ch[p][i]),val[ch[p][i]]|=val[fi[ch[p][i]]];
else ch[p][i]=ch[fi[p]][i];
}
}
void printans(int p,int s) {
if(p) {
printans(from[p][s].first, from[p][s].second);
cout<<chr[p][s];
}
}
void bfs() {
queue <pair<int,int> > q;
q.push({0,0});
vis[0][0]=1;
while(q.size()) {
pair<int,int> pr = q.front();
q.pop();
int p=pr.first, s=pr.second;
for(int i=0;i<26;i++) {
int p1=ch[p][i], s1=s|val[p1];
if(!vis[p1][s1]) {
q.push({p1,s1});
from[p1][s1]={p,s};
chr[p1][s1]=i+'A';
vis[p1][s1]=1;
if(s1==(1<<n)-1) {
printans(p1,s1);
return;
}
}
}
}
}
char str[N];
int main() {
cin>>n;
for(int i=1;i<=n;i++) cin>>str,ins(str,i-1);
build();
bfs();
}