【题目链接】
【题意】
原题来自: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 ",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 }