【洛谷 P3808】【AC自动机】 AC自动机(简单版)
题目
解题思路
建一个trie树然后在上面跑kmp
代码
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
string s;
int x,l,c,w,n,ans,tot,q[1000010],tr[500010][30],ed[500010],nxt[1000010];
void add() //建trie树
{
x=0,l=s.size();
for (int i=0;i<l;i++)
{
c=s[i]-'a';
if (tr[x][c]==0) tr[x][c]=++tot;
x=tr[x][c];
}
ed[x]++;
return;
}
void bfs() //求出失配后跳转的next
{
int h=0,t=0;
for (int i=0;i<26;i++)
if (tr[0][i]>0) nxt[tr[0][i]]=0,q[++t]=tr[0][i];
while (h<t)
{
h++;
x=q[h];
for (int i=0;i<26;i++)
{
if (tr[x][i]==0) tr[x][i]=tr[nxt[x]][i]; //失配了,直接跳转
else {
q[++t]=tr[x][i]; //可以走,入队
nxt[tr[x][i]]=tr[nxt[x]][i]; //保存next
}
}
}
}
void find() //求结果
{
x=0,l=s.size();
for (int i=0;i<l;i++)
{
c=s[i]-'a';
int k=tr[x][c];
while (k>0&&ed[k]>-1)
{
ans+=ed[k];
ed[k]=-1; //避免重复计算
k=nxt[k];
}
x=tr[x][c];
}
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
cin>>s;
add();
}
bfs();
cin>>s;
find();
printf("%d\n",ans);
}