【题目链接】
【题意】
原题来自:HDU 2222
给定 n 个长度不超过 50 的由小写英文字母组成的单词准备查询,以及一篇长为 m 的文章,问:文中出现了多少个待查询的单词。多组数据。
【题解】
模板题
【代码】

1 #pragma GCC optimize(2)
2
3 #include<queue>
4 #include<cstdio>
5 #include<cstring>
6 #include<iostream>
7 #include<algorithm>
8 using namespace std;
9 const int N = 5e5+1e4;
10 const int M = 1e6+10;
11 queue < int > Q ;
12 typedef struct Aho_Corasick_Automaton{
13 int Son[N][26],End[N],Fail[N],idx;
14 void Init(){
15 idx = 0 ;
16 while( !Q.empty() ) Q.pop() ;
17 memset(Son , 0 , sizeof Son );
18 memset(End , 0 , sizeof End );
19 memset(Fail, 0 , sizeof Fail );
20 }
21 void Insert(char s[]){
22 int p = 0 ;
23 for(int i=0;s[i];i++){
24 int t = s[i] - 'a';
25 if( !Son[p][t] )
26 Son[p][t] = ++idx;
27 p = Son[p][t] ;
28 }
29 End[p] ++ ;
30 }
31
32 void Build(){
33 for(int i=0;i<26;i++){
34 if( Son[0][i] )
35 Fail[Son[0][i]] = 0 ,Q.push(Son[0][i]);
36 }
37
38 while( !Q.empty() ){
39 int u = Q.front() ;
40 Q.pop();
41
42 for(int i=0;i<26;i++){
43 if( Son[u][i] ){
44 Fail[Son[u][i]] = Son[Fail[u]][i] ;
45 Q.push( Son[u][i] );
46 }else{
47 Son[u][i] = Son[Fail[u]][i];
48 }
49 }
50 }
51 }
52
53 void Query(char s[]){
54 int p = 0,res = 0;
55 for(int i=0;s[i];i++){
56 int t = s[i] - 'a';
57 p = Son[p][t] ;
58 for(int j=p ; j && ~End[j] ; j = Fail[j] ){
59 res += End[j] ;
60 End[j] = -1 ;
61 }
62 }
63 //printf("%d\n",res);
64 cout << res << endl ;
65 }
66 }AC_Machine ;
67 AC_Machine AC ;
68 char s[M];
69 int n;
70 int main(){
71
72 ios_base :: sync_with_stdio(false);
73 cin.tie(NULL) , cout.tie(NULL);
74 int T;
75 cin >> T ;
76 while(T--){
77 cin >> n ;
78 AC.Init();
79 for(int i=0;i<n;i++){
80 //scanf("%s",s);
81 cin >> s ;
82 AC.Insert(s);
83 }
84 AC.Build();
85 //scanf("%s",s);
86 cin >> s ;
87 AC.Query(s);
88 }
89 return 0;
90 }
