洛谷P3808 【模板】AC自动机(简单版) AC自动机
网址:https://www.luogu.org/problem/P3808
题意:
给定$n$个模式串和$1$个文本串,求有多少个模式串在文本串里出现过,相同的模式串需要多次计算。
题解:
$AC$自动机的模板题。$AC$自动机是基于$Trie$树的有限状态自动机,又称$Trie$图,$AC$自动机的结点的$fail$指针构造方法如下:在$Trie$树上,类似于$KMP$的$fail$指针,对于非空结点,找到其父亲的$fail$指针对应的结点的相同字母的儿子结点。对于空节点,直接把它连到其父亲的$fail$指针对应的结点的相同字母的儿子结点,根结点的儿子的$fail$指针指向根,形成转移图。然后查询的时候,我们要求的是求出现次数,所以我们当到达一个结点的时候,我们可以跳$fail$指针匹配其后缀,然后匹配过的加上标记防止重新匹配。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | #include <iostream> #include <string> #include <queue> using namespace std; #define maxn int(2e6+5) int trie[maxn][26]; int cntword[maxn]; int fail[maxn]; int cnt = 0; struct ac { void insert(string& str) //插入字符串 { int root = 0, next; for ( int i = 0; i < str.size(); ++i) { next = str[i] - 'a' ; if (!trie[root][next]) trie[root][next] = ++cnt; //将字符的位置按照放入顺序递增 root = trie[root][next]; } ++cntword[root]; //该位置单词结束 } void buildfail() { queue< int >que; for ( int i = 0; i < 26; ++i) { if (trie[0][i]) { fail[trie[0][i]] = 0; //根的儿子的fail一定指向根 que.push(trie[0][i]); //将其放入队列 } } while (!que.empty()) { int now = que.front(); //出队,以其为根 que.pop(); for ( int i = 0; i < 26; ++i) { if (trie[now][i]) { fail[trie[now][i]] = trie[fail[now]][i]; //fail指向其父节点的fail对应的相同子节点 que.push(trie[now][i]); } else trie[now][i] = trie[fail[now]][i]; //空节点是其父节点对应fail的相同儿子 } } } int query(string& str) { int now = 0, ans = 0; for ( int i = 0; i < str.size(); ++i) { now = trie[now][str[i] - 'a' ]; for ( int j = now; j && cntword[j] != -1; j = fail[j]) //匹配根到当前结点的子串的后缀以节省时间 { ans += cntword[j]; cntword[j] = -1; } } return ans; } }; int main() { string tmp; ios::sync_with_stdio(0); cin.tie(0); ac AC; int n; cin >> n; for ( int i = 0; i < n; ++i) { cin >> tmp; AC.insert(tmp); } fail[0] = 0; cin >> tmp; AC.buildfail(); cout << AC.query(tmp) << endl; return 0; } |
AC代码:
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步