https://blog.csdn.net/creatorx/article/details/71100840
AC自动机就是一直跳fail边,然后找到整个要匹配的串就行了。
fail边:大概就是指向以当前节点表示的字符 为最后一个字符的 最长当前字符串的 后缀字符串的 最后一个节点(摘自上面的博客并断句)
代码:luogu3808
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
int n;
const int N=500010;
struct ACZDJ {
int tr[N][26],fail[N],val[N],cnt;
void insert(char *s) {
int len=strlen(s),p=0;
for(int i=0; i<len; i++) {
if(!tr[p][s[i]-'a']) tr[p][s[i]-'a']=++cnt;
p=tr[p][s[i]-'a'];
}
val[p]++;
}
void build() {
queue<int>q;
for(int i=0; i<26; i++)
if(tr[0][i]) q.push(tr[0][i]),fail[tr[0][i]]=0;
while(!q.empty()) {
int u=q.front();
q.pop();
for(int i=0; i<26; i++) {
if(tr[u][i]) q.push(tr[u][i]),fail[tr[u][i]]=tr[fail[u]][i];
else tr[u][i]=tr[fail[u]][i];
}
}
}
int query(char *s) {
int len=strlen(s),p=0,ans=0;
for(int i=0; i<len; i++) {
int v=s[i]-'a';
p=tr[p][v];
for(int j=p; ~val[j]&&j; j=fail[j]) {
ans+=val[j];
val[j]=-1;
}
}
return ans;
}
} AC;
char s[2000005];
int main() {
scanf("%d",&n);
while(n--) {
scanf("%s",s);
AC.insert(s);
}
AC.build();
scanf("%s",s);
cout<<AC.query(s);
}