AC自动机

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,cnt=0,didx=0,idx[N],ans[N];
string s[N];
struct Node
{
    int son[26],idx,fail,ans;
    Node()
    {
        memset(son,0,sizeof(son));
        idx=fail=ans=0;
    }
};
vector<vector<int>> failt;
vector<Node> tr;
void jf()
{
    queue<int> q;
    for(int i=0;i<26;i++)
        if(tr[0].son[i])
        {
            q.push(tr[0].son[i]);
            failt[0].push_back(tr[0].son[i]);//用于建立fail的树,注意是反向建边
        }
    while(!q.empty())
    {
        int t=q.front();
        q.pop();
        for(int i=0;i<26;i++)
        {
            if(tr[t].son[i])
            {
                tr[tr[t].son[i]].fail=tr[tr[t].fail].son[i];
                q.push(tr[t].son[i]);
                failt[tr[tr[t].fail].son[i]].push_back(tr[t].son[i]);//用于建立fail的树,注意是反向建边
            }   
            else
                tr[t].son[i]=tr[tr[t].fail].son[i];
        }
    }
}
void query()
{
    string st;
    cin>>st;
    int u=0;
    for(char x:st)
    {
        u=tr[u].son[x-'a'];
        tr[u].ans+=1;
    }
}
void dfs(int u)
{
    for(int v:failt[u])
    {
        dfs(v);
        tr[u].ans+=tr[v].ans;//回溯时统计
    }
    ans[tr[u].idx]=tr[u].ans;
}
int main()
{
    cin>>n;
    tr.emplace_back();
    for(int i=1;i<=n;i++)
    {
        string st;
        cin>>st;
        int u=0;
        for(char x:st)
        {
            if(!tr[u].son[x-'a'])
            {
                tr[u].son[x-'a']=++cnt;
                tr.emplace_back();
            }
            u=tr[u].son[x-'a'];
        }
        //上面是建树
        if(!tr[u].idx)
            tr[u].idx=++didx;
        idx[i]=tr[u].idx;//idx数组去重用
    }
    failt.resize(tr.size());
    jf();
    query();
    dfs(0);
    for(int i=1;i<=n;i++)
        cout<<ans[idx[i]]<<"\n";
}
posted @ 2025-11-13 21:33  wtnbl  阅读(4)  评论(0)    收藏  举报