ac自动机
参考博客:https://blog.csdn.net/bestsort/article/details/82947639
#include<queue>
#include<cstdlib>
#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdio>
#define debug(x) cout<<#x<<" = "<<x<<endl
#define gg cout<<"-----QAQ-----"<<endl
using namespace std;
typedef long long ll;
const int maxn = 500010;
int trie[maxn][26];
int cntword[maxn];
int fail[maxn];
int cnt = 0;
void insertWords(string s)
{
int root = 0;
for(int i = 0; i <s.size(); ++i) {
int next = s[i]-'a';
if(!trie[root][next])
trie[root][next] = ++cnt;
root = trie[root][next];
}
cntword[root]++;
}
void getFail()
{
queue<int> q;
for(int i = 0; i < 26; ++i) {
if(trie[0][i]) {
fail[trie[0][i]] = 0;
q.push(trie[0][i]);
}
}
while(!q.empty()){
int now = q.front();q.pop();
for(int i = 0; i < 26; ++i) {
if(trie[now][i]) {
fail[trie[now][i]] = trie[fail[now]][i];
q.push(trie[now][i]);
}
else trie[now][i] = trie[fail[now]][i];
}
}
}
int query(string s)
{
int now = 0, ans = 0;
for(int i = 0; i < s.size(); ++i) {
now = trie[now][s[i]-'a'];
for(int j = now; j&&cntword[j]!=-1;j=fail[j]) {
ans += cntword[j];
cntword[j] = -1;
}
}
return ans;
}
void init()
{
cnt = 0;
for(int i = 0; i < 26; ++i) {
for(int j = 0; j < maxn; ++j)
trie[j][i] = 0;
}
memset(fail, 0, sizeof(fail));
memset(cntword, 0, sizeof(cntword));
}
void solve()
{
init();
int n;string s;
cin >> n;
for(int i = 1; i <= n; ++i) {
cin >> s;
insertWords(s);
}
getFail();
cin >> s;
cout<<query(s)<<endl;
}
int main()
{
int t;
cin >> t;
while(t--)
solve();
return 0;
}