这题直接用AC自动机模板再加上这个结点已经被访问过了该结点就不需要再使用因为查找的字符串只有一个,所以直接把这个结点对应的值重置为0,如果有多个用标记数组标记一下有没有用过即可
题目链接
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<iostream>
using namespace std;
#define mes(s) memset(s,0,sizeof(s))
const int mx = 1e6+5;
char s[mx];
struct trie{
int ch[mx][26];
int v[mx],f[mx],last[mx];
int sz;
void init(){mes(ch[0]),sz = 1,mes(v),mes(f),mes(last);}
int idx(char c){return c-'a';}
void insert(char *s){
int len = strlen(s);
int u = 0;
for(int i = 0; i < len; i++){
int d = idx(s[i]);
if(!ch[u][d]){
mes(ch[sz]);
ch[u][d] = sz++;
}
u = ch[u][d];
}
v[u]++;
}
void getfail(){
queue<int>q;
for(int d = 0; d < 26; d++){
if(!ch[0][d]){
ch[0][d] = 0;
continue;
}
int ret = ch[0][d];
last[ret] = f[ret] = 0;
q.push(ret);
}
while(!q.empty()){
int u = q.front();
q.pop();
for(int d = 0; d < 26; d++){
if(!ch[u][d]){
ch[u][d] = ch[f[u]][d];
continue;
}
int ret = ch[u][d];
f[ret] = ch[f[u]][d];
last[ret] = v[f[ret]]?f[ret]:last[f[ret]];
q.push(ret);
}
}
}
int find(char *s){
int ans = 0,u = 0;
int len = strlen(s);
for(int i = 0; i < len; i++){
int d = idx(s[i]);
int ret = ch[u][d];
while(ret){
ans += v[ret];
v[ret] = 0;
ret = last[ret];
}
u = ch[u][d];
}
return ans;
}
}word;
int main(){
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
word.init();
for(int i = 1; i <= n; i++){
scanf("%s",s);
word.insert(s);
}
word.getfail();
scanf("%s",s);
printf("%d\n",word.find(s));
}
}