AC 自动机
OI-wiki Link and bilibili Link
AC 自动机,主要用于解决多模式串(即需要求出出现次数等的串)匹配的问题,基于字典树。
大致
将模式串建到字典树上,对每个字典树上的节点求出失配指针,根据失配指针建立失配树,用失配树来维护模式串出现次数。
具体构建
建立字典树
略。
失配 fail 指针
失配指针用于辅助多模式串匹配。
节点
由于是最长可匹配后缀,那么我们可以发现,只要我们不断枚举 fail[x], fail[fail[x]] ...
,就可以把其每个可匹配后缀都枚举出来。
当字典树上一个节点
但这样做的复杂度似乎不太对,考虑优化。
路径压缩优化(字典图)
为了避免反复枚举一个转移
由于这个操作改变了字典树的结构,所以也被称为建立字典图。
建立 fail 树
求出 fail 后,一般都需要用 fail 树来辅助维护答案。
顾名思义,就是以
至此,AC 自动机的前置搭建已经完成,那么就是处理匹配的问题了。
处理匹配
仍然是在字典图上面处理,求出答案后把标记打在失配树上,最后用失配树来处理答案。
假设现在匹配到了
最后求答案即可。
Code
#include <iostream> #include <vector> #include <algorithm> #define _1 (__int128)1 using namespace std; using ll = long long; void FileIO (const string s) { freopen((s + ".in").c_str(), "r", stdin); freopen((s + ".out").c_str(), "w", stdout); } const int N = 2e5 + 10; int n, trie[N][30], ndcnt, fail[N], cnt[N], ans[N]; string s; vector<int> id[N], g[N]; pair<int, int> dfn[N]; void Insert (string s, int x) { int now = 0; for (int i = 0; i < s.size(); i++) { if (!trie[now][s[i] - 'a']) trie[now][s[i] - 'a'] = ++ndcnt, dfn[ndcnt] = {i, ndcnt}; now = trie[now][s[i] - 'a']; } id[now].push_back(x); } void Get (int x) { for (int i : g[x]) Get(i), cnt[x] += cnt[i]; for (int i : id[x]) ans[i] = cnt[x]; } signed main () { ios::sync_with_stdio(0), cin.tie(0); // FileIO(""); cin >> n; for (int i = 1; i <= n; i++) cin >> s, Insert(s, i); cin >> s; sort(dfn + 1, dfn + ndcnt + 1); for (int i = 1; i <= ndcnt; i++) { int x = dfn[i].second; for (int j = 0; j < 26; j++) { if (trie[x][j]) fail[trie[x][j]] = trie[fail[x]][j]; else trie[x][j] = trie[fail[x]][j]; } } for (int i = 1; i <= ndcnt; i++) g[fail[i]].push_back(i); for (int i = 0, j = 0; i < s.size(); i++) { if (trie[j][s[i] - 'a']) j = trie[j][s[i] - 'a']; else j = trie[fail[j]][s[i] - 'a']; cnt[j]++; } Get(0); for (int i = 1; i <= n; i++) cout << ans[i] << '\n'; return 0; }
例题
本文作者:wnsyou の blog
本文链接:https://www.cnblogs.com/wnsyou-blog/p/18538588/ac-automaton
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步