洛谷 P3808 【模板】AC自动机(简单版)
【是先看了洛谷详解大致理解了,又看这个深度理解了fail指针和trie图以及query函数】
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxN = 1000000 + 7;
struct AC_automat{
int trie[maxN][26], tot;
int fail[maxN], sum[maxN];
void Clear(int rt)
{
for(int i = 0; i < 26; i ++ )
trie[rt][i] = 0;
sum[rt] = 0 ;
}
void init()
{
tot = 0;
Clear(0);
}
void Insert(char *s)
{
int rt = 0;
for(int i = 0; s[i]; i ++ )
{
int id = s[i] - 'a';
if(!trie[rt][id]) { trie[rt][id] = ++ tot; Clear(tot); }
rt = trie[rt][id];
}
sum[rt]++ ;
}
void build()
{
memset(fail, 0, sizeof(fail));
queue<int>que;
for(int i = 0; i < 26; i ++ )
if(trie[0][i]) que.push(trie[0][i]);
while(!que.empty())
{
int rt = que.front(); que.pop();
for(int i = 0; i < 26; i ++ )
{
if(trie[rt][i])
{
fail[trie[rt][i]] = trie[fail[rt]][i];
que.push(trie[rt][i]);
} else trie[rt][i] = trie[fail[rt]][i];
}
}
}
int query(char *t)
{
int ans = 0;
int now = 0;
for(int i = 0; t[i]; i ++ )
{
int id = t[i] - 'a';
now = trie[now][id];
for(int nex = now; nex && ~sum[nex]; nex = fail[nex])
ans += sum[nex], sum[nex] = -1;
}
return ans;
}
}ac_auto;
int n;
char s[maxN];
int main()
{
scanf("%d", &n);
ac_auto.init();
for(int i = 0; i < n; i ++ )
{
scanf("%s", s);
ac_auto.Insert(s);
}
ac_auto.build();
scanf("%s", s);
printf("%d\n", ac_auto.query(s));
return 0;
}
/*
6
she
her
he
him
his
e
hisheher
ans = 5:his\she\he\e\her
*/
来源:CSDN
作者:Eve_Miracle*
链接:https://blog.csdn.net/weixin_44049850/article/details/104182836