AC自动机一直搜即可
注意每次+end[i]后,需要把end[i]=0,避免重复计算
#include<stdio.h>
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define MEM(a,x) memset(a,x,sizeof(a))
#define lowbit(x) ((x)&-(x))
using namespace std;
struct Trie{
const static int maxn=5e5+5;
const static int BASE='a';
const static int N = 26;
int next[maxn][N],end[maxn];
int root,L;
int newNode(){
MEM(next[L],-1);
end[L++]=0;
return L-1;
}
void init(){
L=0;
root=newNode();
}
void insert(char buf[]){
int now=root;
for(int i=0;buf[i];++i){
int j=buf[i]-BASE;
if(next[now][j]==-1){
next[now][j]=newNode();
}
now=next[now][j];
}
end[now]++;
}
//ac自动机
int fail[maxn];
void build(){
queue<int>que;
fail[root]=root;
for(int i=0;i<N;++i){
if(next[root][i]==-1){
next[root][i]=root;
}
else{
fail[next[root][i]]=root;
que.push(next[root][i]);
}
}
while(!que.empty()){
int now=que.front();
que.pop();
for(int i=0;i<N;++i){
if(next[now][i]==-1){
next[now][i]=next[fail[now]][i];
}
else{
fail[next[now][i]]=next[fail[now]][i];
que.push(next[now][i]);
}
}
}
}
ll getNum(int now){
ll ans=0;
while(now!=root){
ans+=end[now];
end[now]=0;
now=fail[now];
}
return ans;
}
ll query(char buf[]){
int now=root;
ll ans=0;
for(int i=0;buf[i];++i){
now=next[now][buf[i]-BASE];
ans+=getNum(now);
}
return ans;
}
}trie;
const int N = 1000000 +5;
char buf[N];
int main()
{
//freopen("/home/lu/code/r.txt","r",stdin);
//freopen("/home/lu/code/w.txt","w",stdout);
int T;
scanf("%d",&T);
while(T--){
int n;
scanf("%d",&n);
trie.init();
while(n--){
scanf("%s",buf);
trie.insert(buf);
}
trie.build();
scanf("%s",buf);
printf("%lld\n",trie.query(buf));
}
return 0;
}