我写了两种做法,AC 自动机的构建都是正确的,不过在对答案上传时的做法不同。
做法 1:只上传了字典树上自己的父亲。
做法 2:在 fail 树上上传 fail[u]。
而显然,做法 1 是错的,但是洛谷的数据能过?HACK 很简单,见这篇讨论。
贴个错误代码(洛谷可 AC):
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
int n,num[maxn][26],cnt,fail[maxn],sum[maxn],idd[maxn];
int q[maxn*26],head,tail;
char s[maxn],t[maxn];
bool viss[maxn][26];
void add(){
int len=strlen(s+1);
int p=0;
for(int i=1;i<=len;i++){
int id=s[i]-'a';
if(!num[p][id]){
num[p][id]=++cnt;
}
p=num[p][id];
}
idd[p]++;
}
void buildAC(){
head=0,tail=-1;
for(int i=0;i<26;i++){
if(num[0][i]){
viss[0][i]=1;
q[++tail]=num[0][i];
}
}
while(head<=tail){
int u=q[head++];
for(int i=0;i<26;i++){
if(num[u][i]){
viss[u][i]=1;
fail[num[u][i]]=num[fail[u]][i];
q[++tail]=num[u][i];
}
else{
num[u][i]=num[fail[u]][i];
}
}
}
}
void dfs(int u){
for(int i=0;i<26;i++){
if(viss[u][i]){
dfs(num[u][i]);
sum[u]+=sum[num[u][i]];
}
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",(s+1));
add();
}
buildAC();
scanf("%s",(t+1));
int m=strlen(t+1);
int p=0;
for(int i=1;i<=m;i++){
int id=t[i]-'a';
p=num[p][id];
sum[p]++;
}
dfs(0);
int ans=0;
for(int i=0;i<=cnt;i++){
if(sum[i]){
ans+=idd[i];
}
}
printf("%d",ans);
return 0;
}