https://www.luogu.com.cn/record/159408403
#include<bits/stdc++.h>
using namespace std;
class Aho_Corasick_Automaton
{
public:
std::vector<std::vector<unsigned> >tr;
std::vector<unsigned>fail;
std::vector<int>state;
public:
Aho_Corasick_Automaton()
{reset();}
unsigned push_new()
{
tr.push_back(std::vector<unsigned>(26,0));
fail.push_back(0);
state.push_back(0);
return tr.size()-1;
}
void reset()
{
tr.clear();
fail.clear();
state.clear();
push_new();
}
void insert(const std::string s,const int flag)
{
unsigned u=0;
const unsigned slen=s.size();
for(unsigned i=0;i<slen;i++)
{
if(tr[u][s[i]-'A']==0)tr[u][s[i]-'A']=push_new();
u=tr[u][s[i]-'A'];
}
state[u]|=flag;//标记
}
void get_fail()
{
std::queue<unsigned>q;
fail[0]=0;
for(int i=0;i<26;i++)if(tr[0][i]!=0){fail[tr[0][i]]=0,q.push(tr[0][i]);}
unsigned u;
while(!q.empty())
{
u=q.front();
q.pop();
for(int i=0;i<26;i++)
{
if(tr[u][i]==0)
{
tr[u][i]=tr[fail[u]][i];
continue;
}
fail[tr[u][i]]=tr[fail[u]][i];
state[tr[u][i]]|=state[fail[tr[u][i]]];//标记传递
q.push(tr[u][i]);
}
}
}
}ac;
int n;string S;
bool vis[602][(1<<12)|1];
struct pack//打包
{unsigned place/*ac自动机中那个点*/;int data/*状态压缩*/;string s/*答案字符串*/;};
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>S;
ac.insert(S,1<<i);
}
ac.get_fail();
queue<pack>q;
vis[0][0]=1;//防止重复访问
q.push(pack{0,0,""});
while(!q.empty())//bfs
{
const auto zzz1=q.front();
q.pop();
if(zzz1.data==(1<<n)-1)
{
cout<<zzz1.s<<endl;
return 0;
}//输出
for(int i=0;i<26;i++)
{
auto zzz2=zzz1;
zzz2.place=ac.tr[zzz2.place][i];//在 trie 图上移动
zzz2.s+=('A'+(char)i);//答案多加一个字符串
zzz2.data|=ac.state[zzz2.place];//碰到这些点
if(!vis[zzz2.place][zzz2.data])
{
vis[zzz2.place][zzz2.data]=1;
q.push(zzz2);//没访问过就入队
}
}//转移
}
return 0;
}