P5357 【模板】AC 自动机

题目背景

本题原为“AC 自动机(二次加强版)”。完成本题前可以先完成 AC 自动机(简单版)AC 自动机(简单版 II) 两道题,为 AC 自动机更简单的应用。

题目描述

给你一个文本串 \(S\)\(n\) 个模式串 \(T_{1 \sim n}\),请你分别求出每个模式串 \(T_i\)\(S\) 中出现的次数。

输入格式

第一行包含一个正整数 \(n\) 表示模式串的个数。

接下来 \(n\) 行,第 \(i\) 行包含一个由小写英文字母构成的非空字符串 \(T_i\)

最后一行包含一个由小写英文字母构成的非空字符串 \(S\)

数据不保证任意两个模式串不相同

输出格式

输出包含 \(n\) 行,其中第 \(i\) 行包含一个非负整数表示 \(T_i\)\(S\) 中出现的次数。

输入输出样例 #1

输入 #1

5
a
bb
aa
abaa
abaaa
abaaabaa

输出 #1

6
0
3
2
1

说明/提示

对于 \(100 \%\) 的数据,\(1 \le n \le 2 \times {10}^5\)\(T_{1 \sim n}\) 的长度总和不超过 \(2 \times {10}^5\)\(S\) 的长度不超过 \(2 \times {10}^6\)

把这个数据加强版的代码稍加修改即可通过另外两题了

题解

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
typedef long long ll;
int n;
int tree[N][26];
int fail[N];
int cnt = 0;
int ed[N];
int t[N];
vector<int>e[N];

void insert(int idx,string s)
{
    int u = 0;
    for(auto ch:s)
    {
        int c = ch - 'a';
        if(tree[u][c]==0)tree[u][c] = ++cnt;
        u = tree[u][c];
    }
    ed[idx] = u;
} 

void setfail()
{
    queue<int>q;
    for(int c =0;c<26;++c)
    {
        if(tree[0][c])q.push(tree[0][c]);
    }
    while(!q.empty())
    {
        int u = q.front();q.pop();
        for(int c=0;c<26;c++)
        {
            if(tree[u][c]==0)
            {
                tree[u][c] = tree[fail[u]][c];
            }
            else
            {
                fail[tree[u][c]] = tree[fail[u]][c];
                q.push(tree[u][c]);
            }
        }
    }
}

void f1(int u)
{
    for(int v:e[u])
    {
        f1(v);
        t[u]+=t[v];
    }
}

void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        string s;
        cin>>s;
        insert(i,s);
    }

    setfail();
    string text;
    cin>>text;
    int u = 0;
    for(auto ch:text)
    {
        int c = ch-'a';
        u = tree[u][c];
        t[u]++;
    }

    for(int i=1;i<=cnt;i++)
    {
        e[fail[i]].push_back(i);
    }

    f1(0);

    for(int i=1;i<=n;i++)
    {
        cout<<t[ed[i]]<<endl;
    }
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int _=1;
    // cin>>_;
    while(_--)
    {
        solve();

    }
    return 0;
}


posted @ 2025-11-28 22:23  屈臣  阅读(5)  评论(0)    收藏  举报