题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1195
多个字符串匹配问题用AC自动机没跑了,建好AC自动机后,由于要求答案要最短和字典序最小,则在AC自动机上状压bfs搜索,bfs保证搜到的串长度最短,然后每次从A-Z遍历,保证搜到的字典序最小。状态压缩成在AC自动机上节点i时,包含了串的状态为j,最后状态为(1<<n)-1时停止。
偷偷懒用cin...
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int n; 5 bool vis[610][4100]; 6 struct node { 7 int num, st; 8 string ans; 9 }; 10 struct ACzd { 11 int AC[610][26]; 12 int fail[610]; 13 int numend[610]; 14 int len, root; 15 int newcode() { 16 memset(AC[len], 0, sizeof(AC[len])); 17 numend[len] = 0; 18 return len++; 19 } 20 void init() { 21 len = 0; 22 root = newcode(); 23 } 24 void build(char *s, int id) { 25 int k = strlen(s); 26 int now = root; 27 for (int i = 0; i < k; i++) { 28 if (AC[now][s[i] - 'A'] == 0) 29 AC[now][s[i] - 'A'] = newcode(); 30 now = AC[now][s[i] - 'A']; 31 } 32 numend[now] |= (1 << id); 33 } 34 void get_fail() { 35 fail[root] = root; 36 queue<int>q; 37 for (int i = 0; i < 26; i++) { 38 if (AC[root][i] != 0) { 39 fail[AC[root][i]] = root; 40 q.push(AC[root][i]); 41 } 42 else 43 AC[root][i] = root; 44 } 45 while (!q.empty()) { 46 int now = q.front(); 47 q.pop(); 48 numend[now] |= numend[fail[now]]; 49 for (int i = 0; i < 26; i++) { 50 if (AC[now][i] != 0) { 51 fail[AC[now][i]] = AC[fail[now]][i]; 52 q.push(AC[now][i]); 53 } 54 else 55 AC[now][i] = AC[fail[now]][i]; 56 } 57 } 58 } 59 string solve() { 60 queue<node>q; 61 int endst = (1 << n) - 1; 62 q.push({ root,0,"" }); 63 while (!q.empty()) { 64 node p = q.front(); 65 q.pop(); 66 if (p.st == endst) { 67 return p.ans; 68 } 69 for (int i = 0; i < 26; i++) { 70 int Nextnum = AC[p.num][i]; 71 int Nextst = p.st | numend[Nextnum]; 72 if (!vis[Nextnum][Nextst]) { 73 vis[Nextnum][Nextst] = 1; 74 q.push({ Nextnum,Nextst,p.ans + (char)(i + 'A') }); 75 } 76 } 77 } 78 } 79 }AC; 80 char s[55]; 81 int main() { 82 ios::sync_with_stdio(0); 83 while (cin >> n) { 84 AC.init(); 85 for (int i = 0; i < n; i++) { 86 cin >> s; 87 AC.build(s, i); 88 } 89 AC.get_fail(); 90 string ans = AC.solve(); 91 cout << ans << endl; 92 } 93 }