题目大意:
给你一些单词,给你一篇文章,需要你求出其中文章中包含了多少个单词?
例如其中的单词she、he、say、shr、her,文章yasherhs。
那么首先根据单词建立出相应的字典树。
和字典树不同的就是AC自动机要建立失败指针,实意就是为了让文章能够一次性的匹配下去。
使得某些单词的后缀能够成为某些单词的前缀,使得模式串匹配的时候不至于浪费掉了之前所匹配的次数。
匹配之后的指针走向:

1 #include<cstdio> 2 #include<cstring> 3 #define N 1000010 4 char str[N]; 5 struct node 6 { 7 node *next[26]; 8 node *fail; 9 int count; 10 node() 11 { 12 count=0,fail=NULL; 13 for(int i=0;i<26;i++)next[i]=NULL; 14 } 15 }*q[500010]; 16 int head,tail; 17 void insert(node *root) 18 { 19 int i=0,index; 20 node *p=root; 21 while(str[i]) 22 { 23 index=str[i]-'a'; 24 if(p->next[index]==NULL)p->next[index]=new node(); 25 p=p->next[index]; 26 i++; 27 } 28 p->count++; 29 } 30 void create_ac(node *root) 31 { 32 root->fail=NULL; 33 q[head++]=root; 34 while(head!=tail) 35 { 36 node *temp=q[tail++]; 37 node *p=NULL; 38 for(int i=0;i<26;i++) 39 { 40 if(temp->next[i]!=NULL) 41 { 42 if(temp==root)temp->next[i]->fail=root; 43 else 44 { 45 p=temp->fail; 46 while(p!=NULL) 47 { 48 if(p->next[i]!=NULL) 49 { 50 temp->next[i]->fail=p->next[i]; 51 break; 52 } 53 p=p->fail; 54 } 55 if(p==NULL)temp->next[i]->fail=root; 56 } 57 q[head++]=temp->next[i]; 58 } 59 } 60 } 61 } 62 int query(node *root) 63 { 64 int answer=0,index,i=0; 65 node *p=root; 66 while(str[i]) 67 { 68 index=str[i]-'a'; 69 while(p->next[index]==NULL&&p!=root)p=p->fail; 70 p=p->next[index]; 71 p=(p==NULL)?root:p; 72 node *temp=p; 73 while(temp->count!=-1&&temp!=root) 74 { 75 answer+=temp->count; 76 temp->count=-1; 77 temp=temp->fail; 78 } 79 i++; 80 } 81 return answer; 82 } 83 int main() 84 { 85 int t,n; 86 scanf("%d",&t); 87 while(t--) 88 { 89 head=tail=0; 90 scanf("%d",&n); 91 node *root=new node(); 92 while(n--) 93 { 94 scanf("%s",str); 95 insert(root); 96 } 97 create_ac(root); 98 scanf("%s",str); 99 printf("%d\n",query(root)); 100 } 101 return 0; 102 }