[模板][P3808]AC自动机(简单版)

时间:2023-11-11 15:40:32

Description:

求n个模式串中有几个在文本串中出现

Solution:

模板,详见代码:

#include<bits/stdc++.h>
using namespace std;
const int mxn=1e7+5;
char str[mxn],p[80];
queue<int > q; namespace Trie {
int tot,fail[mxn],val[mxn];
int t[mxn][26];
void ins(char *s) {
int len=strlen(s),u=0;
for(int i=0;i<len;++i) {
if(!t[u][s[i]-'a']) t[u][s[i]-'a']=++tot;
u=t[u][s[i]-'a'];
}
++val[u];
};
void build() {
for(int i=0;i<26;++i)
if(t[0][i]) fail[t[0][i]]=0,q.push(t[0][i]);
while(!q.empty()) {
int u=q.front(); q.pop();
for(int i=0;i<26;++i) {
if(t[u][i]) fail[t[u][i]]=t[fail[u]][i],q.push(t[u][i]);
else t[u][i]=t[fail[u]][i]; //类似于路径压缩的优化
}
}
};
int query(char *s) {
int len=strlen(s),u=0,ans=0;
for(int i=0;i<len;++i) {
u=t[u][s[i]-'a']; //每次从大到小统计文本串以第i个字符结束的所有串
for(int v=u;val[v]!=-1;v=fail[v])
ans+=val[v],val[v]=-1; //剪枝,跳过无需再跳
}
return ans;
};
}
using namespace Trie; int main()
{
int n; scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%s",p),ins(p);
build();
scanf("%s",str);
printf("%d",query(str));
return 0;
}