AC自动机学习笔记

AC自动机学习笔记

暑训过程中重新学了一遍,简要记录一下随想。

概要

用途

主要用来解决 单词集 \(T\)给定文本串 \(S\) 匹配的问题。
建树复杂度 \(O(\sum |T_i|)\),单词询问复杂度 \(O(|S| + \sum |T_i|)\)

Trie 与 Fail

AC 自动机主要干的事就一件:建两棵树。分别是 Trie 和 Fail,其中后者是在 Trie 的基础上建立的,且为 ACAM 算法的最精髓所在。
注意理解自动机思想和动态规划思想在建树过程中的应用。
定义不多谈论,大概记录一下比较重要的性质。

1

Fail 树是一棵有根树,并且对于该树上的一对节点 \((x,v),v\in subtree(x)\),\(x\) 对应的单词是 \(v\) 对应的单词在 单词集 \(T\) 中的后缀。

2

对于 Fail 树上的一个节点 \(x\),从 \(x\) 到根节点 \(0\) 上所有节点对应单词 \(T_i\) 组成的集合,是单词集中 \(x\) 节点对应的单词的 所有后缀

3

如果每个单词的结尾处对应的 Trie 上节点有权值 \(1\),其余节点权值为 \(0\),那么对于 Fail 树上的一个节点 \(x\),其对应单词的出现次数就是在 Fail 树中\(x\) 为根节点的权值和

根据这个性质,可以完成十分经典的 ACAM 应用:分别数出多个模式串 \(T_i\) 在文本串 \(S\) 中出现的次数。

Code

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int tr[N][26],fail[N],cnt;
int idx[N],ans[N];
inline void insert(string &s,int id)
{
    int p=0;
    for(char c:s)
    {
        if(!tr[p][c-'a'])tr[p][c-'a']=++cnt;
        p=tr[p][c-'a'];
    }   
    idx[id]=p;
}
int in[N];
inline void build()
{
    queue<int> q;
    for(int i=0;i<26;++i)if(tr[0][i])q.push(tr[0][i]);
    while(q.size())
    {
        int x=q.front();q.pop();
        for(int i=0;i<26;++i)
        {
            if(tr[x][i])fail[tr[x][i]]=tr[fail[x]][i],q.push(tr[x][i]),in[tr[fail[x]][i]]++;
            else tr[x][i]=tr[fail[x]][i];
        }
    } 
}
inline void query(string &s)
{
    int p=0;
    for(char c:s)
    {
        p=tr[p][c-'a'];
        ans[p]++;
    }
}
inline void bfs()
{
    queue<int> q;
    for(int i=1;i<=cnt;++i)if(!in[i])q.push(i);
    while(q.size())
    {
        int x=q.front();q.pop();
        int v=fail[x];
        ans[v]+=ans[x];
        if(!(--in[v]))q.push(v);
    }
}
inline void solve()
{
    int n;
    cin>>n;
    string s,t;
    for(int i=1;i<=n;++i)
    {
        cin>>t;
        insert(t,i);
    }
    build();
    cin>>s;
    query(s);
    bfs();
    for(int i=1;i<=n;++i)cout<<ans[idx[i]]<<'\n';
}

int main()
{
    ios::sync_with_stdio(0);cin.tie(0);
    return solve(),0;
}

ACAM与动态规划

//todo here

ACAM与矩阵乘法递推

//todo here

posted @ 2025-08-26 01:11  Hanggoash  阅读(9)  评论(0)    收藏  举报
动态线条
动态线条end