AC自动机

  1. 初始化失配指针:
    • 根节点的失配指针指向自身。
    • 根节点的所有子节点的失配指针指向根节点。
    • 对于其他节点,使用广度优先搜索(BFS)的方式逐层计算失配指针。对于一个节点u,假设其父节点为p,且从p到u的边对应的字符为c,则找到p的失配指针所指向的节点q,如果q有字符c对应的子节点v,则将u的失配指针指向v;如果没有,则继续沿着q的失配指针向上查找,直到找到合适的节点或者到达根节点。
  2. 匹配过程
    • 从文本的第一个字符开始,从根节点开始在 AC 自动机上进行匹配。对于文本中的每个字符c:
      如果当前节点有字符c对应的子节点,则移动到该子节点。
      如果没有,则沿着当前节点的失配指针向上跳转,直到找到有字符c对应的子节点或者到达根节点。
      每到达一个节点,检查该节点及其失配指针所指向的节点是否为某个模式串的结尾,如果是,则记录匹配信息。

板子

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int ch[N][27],cnt[N];
int idx;
void insert(string s)
{
    int l=s.size();
    int p=0;
    for(int i=0;i<l;i++)
    {
        int x=s[i]-'a'+1;
        if(!ch[p][x])   
            ch[p][x]=++idx;
        p=ch[p][x];
    }
    cnt[p]++;
}
int nxt[N];
void build()
{
    queue<int> q;
    for(int i=1;i<=26;i++)
    {
        if(ch[0][i])
            q.push(ch[0][i]);
    }
    while(q.size())
    {
        int u=q.front();
        q.pop();
        for(int i=1;i<=26;i++)
        {
            int v=ch[u][i];
            if(v)   
                nxt[v]=ch[nxt[u]][i],q.push(v);
            else
                ch[u][i]=ch[nxt[u]][i];
        }
    }
}
int query(string s)
{
    int l=s.size();
    int q=0;
    int ans=0;
    for(int i=0;i<l;i++)
    {
        int x=s[i]-'a'+1;
        q=ch[q][x];
        for(int j=q;j&&~cnt[j];j=nxt[j])
            ans+=cnt[j],cnt[j]=-1;
    }
    return ans;
}

int main()
{

    return 0;
}
posted @ 2025-02-28 07:37  流氓兔LMT  阅读(14)  评论(0)    收藏  举报