#include <cstdio> #include <cstring> #include <queue> using namespace std; const int size=26; char key[55],dir[1000005]; class ac_auto { public: ac_auto *fail; ac_auto *next[size]; int cnt; ac_auto() { fail=NULL; cnt=0; memset(next,NULL,sizeof(next)); }; void Insert(ac_auto *root,char *str) //构造trie树 { int i=0,index; ac_auto *tmp=root; while(str[i]) { index=str[i]-'a'; if(tmp->next[index]==NULL) tmp->next[index]=new ac_auto(); tmp=tmp->next[index]; i++; } tmp->cnt++; //单词结尾,计数加1 }; void build(ac_auto *root) //构造自动机 { queue<ac_auto*> que; int i; ac_auto *tmp,*p; root->fail=NULL; que.push(root); while(!que.empty()) { tmp=que.front(); que.pop(); p=NULL; for(i=0;i<size;++i) { if(tmp->next[i]!=NULL) { if(tmp==root) tmp->next[i]->fail=root; else { p=tmp->fail; while(p!=NULL) { if(p->next[i]!=NULL) { tmp->next[i]->fail=p->next[i]; break; } p=p->fail; } if(p==NULL) tmp->next[i]->fail=root; } que.push(tmp->next[i]); } } } }; int query(char *str,ac_auto *root) //查询,返回之前构造的树中有多少字串出现在str中 { int i=0,count=0,index,len=strlen(str); ac_auto *tmp=root,*t; while(str[i]) { index=str[i]-'a'; while(tmp->next[index]==NULL && tmp!=root) tmp=tmp->fail; tmp=tmp->next[index]; if(tmp==NULL) tmp=root; t=tmp; while(t!=root) { cnt+=t->cnt; t->cnt=0; t=t->fail; } i++; } return cnt; }; }; int main() { int cas,n; scanf("%d",&cas); while(cas--) { ac_auto *root = new ac_auto(); scanf("%d",&n); while(n--) { scanf("%s",key); root->Insert(root,key); } root->build(root); scanf("%s",dir); printf("%d/n",root->query(dir,root)); } return 0; }