BZOJ1195:[HNOI2006]最短母串(AC自动机,BFS)
Description
给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串。
Input
第一行是一个正整数n(n<=12),表示给定的字符串的个数。
以下的n行,每行有一个全由大写字母组成的字符串。每个字符串的长度不超过50.
Output
只有一行,为找到的最短的字符串T。在保证最短的前提下,
如果有多个字符串都满足要求,那么必须输出按字典序排列的第一个。
Sample Input
2
ABCD
BCDABC
ABCD
BCDABC
Sample Output
ABCDABC
Solution
先建好$AC$自动机,然后每个结束点用状压标记一下包含状态。
从根开始$BFS$,找到答案就停止,这样可以保证最短。
每次扩展按字典序从小到大扩展,这样可以保证字典序最小。
$BFS$的时候存下前驱输出答案就好了。
建立$fail$指针的时候,当$now$点建完的时候,要往上暴跳$fail$,把$fail$上包含状态并到$now$上!我沙茶忘了这里找了好久错误TAT
卡空间真的丧病……
Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<queue> 5 #define N (601) 6 using namespace std; 7 8 struct Node{int p,S,id;}; 9 int n,sz,cnt,Son[N][26],End[N],Fail[N]; 10 int pre[N*3000],ans[N*3000]; 11 bool vis[N][1<<12]; 12 queue<int>q; 13 queue<Node>Q; 14 char s[N]; 15 16 void Insert(char s[],int id) 17 { 18 int now=0; 19 for (int i=0,l=strlen(s); i<l; ++i) 20 { 21 int x=s[i]-'A'; 22 if (!Son[now][x]) Son[now][x]=++sz; 23 now=Son[now][x]; 24 } 25 End[now]|=(1<<(id-1)); 26 } 27 28 void Build_Fail() 29 { 30 for (int i=0; i<26; ++i) 31 if (Son[0][i]) q.push(Son[0][i]); 32 while (!q.empty()) 33 { 34 int now=q.front(); q.pop(); 35 for (int i=0; i<26; ++i) 36 { 37 if (!Son[now][i]) 38 { 39 Son[now][i]=Son[Fail[now]][i]; 40 continue; 41 } 42 Fail[Son[now][i]]=Son[Fail[now]][i]; 43 q.push(Son[now][i]); 44 } 45 int t=Fail[now]; 46 while (t && !End[t]) t=Fail[t]; 47 End[now]|=End[t]; 48 } 49 } 50 51 void Print(int x) 52 { 53 if (!x) return; 54 Print(pre[x]); printf("%c",ans[x]+'A'); 55 } 56 57 void Solve() 58 { 59 Q.push((Node){0,0,0}); 60 vis[0][0]=true; 61 while (!Q.empty()) 62 { 63 Node tmp=Q.front(); Q.pop(); 64 int p=tmp.p,S=tmp.S; 65 if (S==(1<<n)-1) {Print(tmp.id); return;} 66 for (int i=0; i<26; ++i) 67 if (!vis[Son[p][i]][S|End[Son[p][i]]]) 68 { 69 vis[Son[p][i]][S|End[Son[p][i]]]=true; 70 ++cnt; ans[cnt]=i; pre[cnt]=tmp.id; 71 Q.push((Node){Son[p][i],S|End[Son[p][i]],cnt}); 72 } 73 } 74 } 75 76 int main() 77 { 78 scanf("%d",&n); 79 for (int i=1; i<=n; ++i) 80 scanf("%s",s),Insert(s,i); 81 Build_Fail(); Solve(); 82 }