模板AC自动机
Posted 蒟蒻zht的博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板AC自动机相关的知识,希望对你有一定的参考价值。
一道模板题,但对于我这种初学者来说也是不好做的。
对于AC自动机的理解,本蒟蒻暂时还理解不好,不多说了。
看看这个人的blog。
——本题代码
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 #define N 500005 6 7 using namespace std; 8 9 char s[N << 1]; 10 int T, n, sz, ans; 11 int ch[N][26], val[N], fail[N]; 12 bool vis[N]; 13 queue <int> q; 14 15 inline void clear() 16 { 17 n = sz = ans = 0; 18 memset(ch, 0, sizeof(ch)); 19 memset(vis, 0, sizeof(vis)); 20 memset(val, 0, sizeof(val)); 21 memset(fail, 0, sizeof(fail)); 22 } 23 24 inline void insert() 25 { 26 int i, x, len = strlen(s), now = 0; 27 for(i = 0; i < len; i++) 28 { 29 x = s[i] - ‘a‘; 30 if(!ch[now][x]) ch[now][x] = ++sz; 31 now = ch[now][x]; 32 } 33 val[now]++; 34 } 35 36 inline void make_fail() 37 { 38 int i, now; 39 while(!q.empty()) q.pop(); 40 //第二层特殊处理,将第二层节点的 fail 指针指向 root(其实就是0,也就不用管) 41 for(i = 0; i < 26; i++) 42 if(ch[0][i]) 43 q.push(ch[0][i]); 44 while(!q.empty()) 45 { 46 now = q.front(), q.pop(); 47 for(i = 0; i < 26; i++) 48 { 49 if(!ch[now][i]) 50 { 51 ch[now][i] = ch[fail[now]][i]; 52 continue; 53 } 54 fail[ch[now][i]] = ch[fail[now]][i]; 55 q.push(ch[now][i]); 56 } 57 } 58 } 59 60 inline void ac() 61 { 62 int x, y, len = strlen(s), i, now = 0; 63 for(i = 0; i < len; i++) 64 { 65 vis[now] = 1; 66 x = s[i] - ‘a‘; 67 y = ch[now][x]; 68 while(y && !vis[y]) 69 { 70 vis[y] = 1; 71 ans += val[y]; 72 y = fail[y]; 73 } 74 now = ch[now][x]; 75 } 76 } 77 78 int main() 79 { 80 int i; 81 scanf("%d", &T); 82 while(T--) 83 { 84 clear(); 85 scanf("%d", &n); 86 for(i = 1; i <= n; i++) 87 { 88 scanf("%s", s); 89 insert(); 90 } 91 scanf("%s", s); 92 make_fail(); 93 ac(); 94 printf("%d\n", ans); 95 } 96 return 0; 97 }
以上是关于模板AC自动机的主要内容,如果未能解决你的问题,请参考以下文章
HDU3247 Resource Archiver(AC自动机+BFS+DP)
HDU-2222-Keywords Search(AC自动机模板)