传送门biu~
给大家介绍个AC自动机很厉害的人:Duan2baka,我这些炫酷的AC自动机都是跟他学的。
在AC自动机每个节点上加一个
state
s
t
a
t
e
表示状态,第
i
i
位为表示串
i
i
在这个节点被匹配。建完AC自动机后从根节点开始按字典序bfs,继承走过的点的直到所有的串都被匹配。
#include<bits/stdc++.h>
using namespace std;
char s[55];
int n,cnt,fa[2000005],path[2000005];
bool b[1005][1<<12];
struct Node{
Node *ch[26],*nex;
int state,id;
Node(){
for(int i=0;i<26;++i)ch[i]=NULL;
nex=NULL;state=0;id=++cnt;
}
}*root=new Node;
inline void Insert(char s[],int id){
Node *x=root;
for(int i=1;s[i];++i){
int to=s[i]-'A';
if(!x->ch[to]) x->ch[to]=new Node;
x=x->ch[to];
}
x->state|=1<<id>>1;
}
inline void GetFail(){
queue<Node*>q;
root->nex=root;
for(int i=0;i<26;++i){
if(root->ch[i]) q.push(root->ch[i]),root->ch[i]->nex=root;
else root->ch[i]=root;
}
while(!q.empty()){
Node *x=q.front();q.pop();
for(int i=0;i<26;++i){
if(x->ch[i]) q.push(x->ch[i]),x->ch[i]->nex=x->nex->ch[i];
else x->ch[i]=x->nex->ch[i];
}
Node *tmp=x->nex;
while(tmp!=root && !tmp->state) tmp=tmp->nex;
x->state|=tmp->state;
}
}
struct data{
Node *node;
int state,id;
data(){}
data(Node *a,int x,int y){node=a;state=x;id=y;}
};
void print(int x){
if(!x) return;
print(fa[x]);
printf("%c",path[x]+'A');
}
inline void bfs(){
queue<data>q;
q.push(data(root,root->state,cnt=0));b[root->id][root->state]=true;
while(!q.empty()){
data x=q.front();q.pop();
if(x.state==(1<<n)-1){
print(x.id);
return;
}
for(int i=0;i<26;++i){
int now=x.state|x.node->ch[i]->state;
if(b[x.node->ch[i]->id][now]) continue;
b[x.node->ch[i]->id][now]=true;
fa[++cnt]=x.id;path[cnt]=i;
q.push(data(x.node->ch[i],now,cnt));
}
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%s",s+1);
Insert(s,i);
}
GetFail(); bfs();
return 0;
}