AC自动机模板题,网上的好多AC自动机的例子都是用这道题滴。。。汲取没学好KMP的教训,这里讲一下我对AC自动机的理解,一来加深我对AC自动机的理解,二来希望可以帮助读者理解。。
先给出我写的数据结构。。
struct node { int isword; struct node *fail, *next[26]; node() { isword = 0; fail = NULL; for(int i = 0; i < 26; i++) next[i] = NULL; } }*root, *tmp, *now, *p; queue<node*> q;
编程的时候,先写个字典树。。
void inseart(void) { int len = strlen(s), i, temp; now = root; for(i = 0; i < len; i++) { temp = s[i] - 'a'; if(now->next[temp] == NULL) now->next[temp] = new struct node; now = now->next[temp]; } now->isword++; }
void build(void) { int i; root->fail = NULL; q.push(root); while(!q.empty()) { now = q.front(); q.pop(); for(i = 0; i < 26; i++) { if(now->next[i] == NULL) continue; if(now == root) now->next[i]->fail = root; else { p = now->fail; while(p) { if(p->next[i]) { now->next[i]->fail = p->next[i]; break; } p = p->fail; } if(!p) now->next[i]->fail = root; } q.push(now->next[i]); } } }
void search(void) { int len = strlen(s), ans=0, i, temp; now = root; for(i = 0; i < len; i++) { temp = s[i] - 'a'; while(now != root && !now->next[temp]) now = now->fail; if(now->next[temp]) { now = now->next[temp]; p = now; while(p != root && p->isword) { ans += p->isword; p->isword = 0; p = p->fail; } } } printf("%d\n", ans); }
#include <iostream> #include <sstream> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <map> #include <set> #include <bitset> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <climits> #define maxn 1000005 #define eps 1e-6 #define mod 10007 #define INF 99999999 #define lowbit(x) (x&(-x)) //#define lson o<<1, L, mid //#define rson o<<1 | 1, mid+1, R typedef long long LL; using namespace std; struct node { int isword; struct node *fail, *next[26]; node() { isword = 0; fail = NULL; for(int i = 0; i < 26; i++) next[i] = NULL; } }*root, *tmp, *now, *p; queue<node*> q; char s[maxn]; int n; void inseart(void) { int len = strlen(s), i, temp; now = root; for(i = 0; i < len; i++) { temp = s[i] - 'a'; if(now->next[temp] == NULL) now->next[temp] = new struct node; now = now->next[temp]; } now->isword++; } void read(void) { int i; scanf("%d", &n); root = new struct node; for(i = 0; i < n; i++) { scanf("%s", s); inseart(); } scanf("%s", s); } void build(void) { int i; root->fail = NULL; q.push(root); while(!q.empty()) { now = q.front(); q.pop(); for(i = 0; i < 26; i++) { if(now->next[i] == NULL) continue; if(now == root) now->next[i]->fail = root; else { p = now->fail; while(p) { if(p->next[i]) { now->next[i]->fail = p->next[i]; break; } p = p->fail; } if(!p) now->next[i]->fail = root; } q.push(now->next[i]); } } } void search(void) { int len = strlen(s), ans=0, i, temp; now = root; for(i = 0; i < len; i++) { temp = s[i] - 'a'; while(now != root && !now->next[temp]) now = now->fail; if(now->next[temp]) { now = now->next[temp]; p = now; while(p != root && p->isword) { ans += p->isword; p->isword = 0; p = p->fail; } } } printf("%d\n", ans); } int main(void) { int _; while(scanf("%d", &_)!=EOF) { while(_--){ read(); build(); search(); } } return 0; }