洛谷P3808 【模板】AC自动机(简单版)

模板AC自动机

#include<bits/stdc++.h>
#define maxn 5005
#define ll long long
const ll mod=1e9+7;
using namespace std;
const int N = 1e6+10;
const double pi = acos(-1.0);
struct Tree{
    int fail;//失配指针
    int vis[26];//子节点的位置
    int end;//标记有几个单词以这个节点结尾
}AC[N];//trie树
int cnt = 0;//Trie的指针
inline void Build(string s)
{
    int l = s.length();
    int now = 0;
    for(int i=0;i<l;i++)
    {
        if(AC[now].vis[s[i]-'a'] == 0)//Trie树没有这个子节点
        {
            AC[now].vis[s[i]-'a'] = ++cnt;//构造出来
        }
        now = AC[now].vis[s[i]-'a'];//向下构造
    }
    AC[now].end += 1;//标记单词结尾
}
void Get_fail()//构造fail指针
{
    queue<int>Q;
    for(int i=0;i<26;i++)
    {
        if(AC[0].vis[i]!=0)
        {
            AC[AC[0].vis[i]].fail = 0;
            Q.push(AC[0].vis[i]);
        }
    }
    while(!Q.empty())
    {
        int u = Q.front();
        Q.pop();
        for(int i=0;i<26;i++)
        {
            if(AC[u].vis[i]!=0)
            {
                AC[AC[u].vis[i]].fail = AC[AC[u].fail].vis[i];
                Q.push(AC[u].vis[i]);
            }
            else
                AC[u].vis[i] = AC[AC[u].fail].vis[i];
        }
    }
}
int AC_Query(string s)
{
    int l = s.length();
    int now = 0,ans = 0;
    for(int i=0;i<l;i++)
    {
        now = AC[now].vis[s[i]-'a'];
        for(int t=now;t&&AC[t].end!=-1;t=AC[t].fail)
        {
            ans += AC[t].end;
            AC[t].end = -1;
        }
    }
    return ans;
}
int main()
{
    int n;
    string s;
    cin >> n;
    for(int i=1;i<=n;i++)
    {
        cin >> s;
        Build(s);
    }
    AC[0].fail = 0;
    Get_fail();
    cin >> s;
    cout << AC_Query(s) << "\n";
}
posted @ 2020-10-04 23:31  hh13579  阅读(119)  评论(0编辑  收藏  举报