

1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 int T,n; 7 char ci[51],zhu[1000001]; 8 struct actrie{ 9 int count; 10 actrie *tr[26],*fail; 11 }; 12 actrie *root; 13 actrie *new_trie(){ 14 actrie *tmp=new actrie; 15 tmp->count=0; 16 for(int i=0;i<26;++i)tmp->tr[i]=NULL; 17 tmp->fail=NULL; 18 return tmp; 19 } 20 void insert(char c[]){ 21 int len=strlen(c+1); 22 actrie *tmp=root; 23 for(int i=1;i<=len;++i){ 24 int index=c[i]-'a'; 25 if(tmp->tr[index]==NULL)tmp->tr[index]=new_trie(); 26 tmp=tmp->tr[index]; 27 } 28 tmp->count++; 29 } 30 int cc; 31 queue<actrie *>dd; 32 void get_fail(){ 33 actrie *tmp=root; 34 tmp->fail=NULL;//the fail of root 35 for(int i=0;i<26;++i) 36 if(tmp->tr[i]!=NULL){ 37 tmp->tr[i]->fail=root; 38 dd.push(tmp->tr[i]); 39 } 40 while(!dd.empty()){ 41 tmp=dd.front();dd.pop(); 42 for(int i=0;i<26;++i) 43 if(tmp->tr[i]!=NULL) 44 { 45 actrie *p=tmp->fail; 46 while(p!=NULL){ 47 if(p->tr[i]!=NULL){ 48 tmp->tr[i]->fail=p->tr[i]; 49 // cout<<++cc<<endl; 50 break; 51 } 52 p=p->fail; 53 } 54 if(p==NULL){ 55 tmp->tr[i]->fail=root; 56 // cout<<++cc<<endl; 57 } 58 dd.push(tmp->tr[i]); 59 } 60 else if(tmp!=root)tmp->tr[i]=tmp->fail->tr[i]; 61 else tmp->tr[i]=root; 62 } 63 } 64 int AC_query(char c[]){ 65 int len=strlen(c+1); 66 int res=0; 67 actrie *tmp=root; 68 for(int i=1;i<=len;++i){ 69 int index=c[i]-'a'; 70 // while(tmp!=root&&tmp->tr[index]==NULL)tmp=tmp->fail; 71 tmp=tmp->tr[index]; 72 if(tmp==NULL)tmp=root; 73 actrie *lin=tmp; 74 while(lin!=root){ 75 if(lin->count==-1)break; 76 res+=lin->count; 77 lin->count=-1; 78 lin=lin->fail; 79 } 80 } 81 return res; 82 } 83 int main(){ 84 scanf("%d",&T); 85 while(T){ 86 --T; 87 scanf("%d",&n); 88 root=new_trie(); 89 for(int i=1;i<=n;++i){ 90 scanf("%s",ci+1); 91 insert(ci); 92 } 93 get_fail(); 94 scanf("%s",zhu+1); 95 printf("%d\n",AC_query(zhu)); 96 } 97 }
不解释,trie图比trie树好用