202ms
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
struct AC_Automaton{
int next[N][26];
int fail[N];
int cnt[N];
int root,tot;
int newnode(){
for(int i=0;i<26;i++){
next[tot][i]=-1;
}
fail[tot]=-1;
cnt[tot]=0;
return tot++;
}
void clear(){
tot=0;
root=newnode();
}
void insert(const string &s){
int p=root;
for(int i=0,len=s.length();i<len;i++){
if(next[p][s[i]-'a']==-1){
next[p][s[i]-'a']=newnode();
}
p=next[p][s[i]-'a'];
}
cnt[p]++;
}
void build(){
queue<int> q;
q.push(root);
while(!q.empty()){
int p=q.front();q.pop();
for(int i=0;i<26;i++){
if(~next[p][i]){
if(p==root) fail[next[p][i]]=root;
else fail[next[p][i]]=next[fail[p]][i];
q.push(next[p][i]);
}else{
if(p==root) next[p][i]=root;
else next[p][i]=next[fail[p]][i];
}
}
}
}
int solve(const string &t){
int p=root,ans=0;
for(int i=0,len=t.length();i<len;i++){
p=next[p][t[i]-'a'];
for(int tmp=p;tmp!=root&&cnt[tmp]!=-1;tmp=fail[tmp]){
ans+=cnt[tmp];
cnt[tmp]=-1;
}
}
return ans;
}
}ac;
int main(){
cin.sync_with_stdio(0);
int cs;
cin>>cs;
while(cs--){
ac.clear();
int n;cin>>n;
for(int i=0;i<n;i++){
string s; cin>>s;
ac.insert(s);
}
ac.build();
string t;
cin>>t;
cout<<ac.solve(t)<<endl;
}
return 0;
}
889ms 计蒜客标程
#include <iostream>
#include<cstring>
using namespace std;
const int MAX_N = 5e5+10;
const int MAX_C = 26;
struct AC_Automaton{
int ch[MAX_N][MAX_C],fail[MAX_N],cnt[MAX_N];// ch 和 cnt 数组与 Trie 树中的一样;fail 保存的是失败指针。ch 和 fail 默认都为 -1
int tot; // Trie 树的总结点(不含根结点)个数
void init(){
memset(ch,-1,sizeof(ch));
memset(fail,0,sizeof(fail));
tot=0;
memset(cnt,0,sizeof(cnt));
}
void insert(char *str){
int p=0;
for(int i=0;str[i];i++){
if(ch[p][str[i]-'a']==-1){
ch[p][str[i]-'a']=++tot;
}
p=ch[p][str[i]-'a'];
}
cnt[p]++;
}
void build(){
int l=0,r=0,Q[MAX_N];
for(int i=0;i<MAX_C;i++){
if(ch[0][i]==-1){
ch[0][i]=0;
}else{
Q[r++]=ch[0][i];
}
}
while(l<r){
int p=Q[l++];
for(int i=0;i<MAX_C;i++){
if(ch[p][i]==-1){
ch[p][i]=ch[fail[p]][i];
}else{
fail[ch[p][i]]=ch[fail[p]][i];
Q[r++]=ch[p][i];
}
}
}
}
int count(char *str){ // 统计字符串集合(Trie)中在给定的一个字符串出现了多少次
int ret=0,p=0;
for(int i=0;str[i];i++){
p=ch[p][str[i]-'a'];
int tmp=p;
while(tmp){
ret+=cnt[tmp];
cnt[tmp]=0; // 避免重复统计同一字符串
tmp=fail[tmp];
}
}
return ret;
}
}ac;
char s[1000006];
int main() {
int cs;
scanf("%d",&cs);
int n;
while(cs--){
ac.init();
scanf("%d",&n);
while(n--){
scanf("%s",s);
ac.insert(s);
}
ac.build();
scanf("%s",s);
printf("%d\n",ac.count(s));
}
return 0;
}