Aho_Corasick自动机(AC自动机)

首先,AC自动机不是Accept自动机,别以为把这段代码复制到OJ上就全都自动AC了……

其实这玩意是Aho-Corasick 造出来的,所以你懂的。
那么这玩意能干嘛咧?
•字符串的匹配问题
•多串的匹配问题※
看不懂吧?解释一下:
例如给几个单词 acbs,asf,dsef,再给出一个 很长的文章,acbsdfgeasf,问在这个文章中,总共出现了多少个单词,或者是单词出现的总次数。
怎么实现的呢,就是KMP+trie树。是以KMP为算法基础,trie为索引结构的东东。那它如何与kmp联系在一起?
•关键是在trie树上加了一种fail指针。
•Fail指针的用途:就像是kmp中的next的数组。
在字符串失配的时候确定转移的节点。AC难点就是指针的算法,看下面这么多图:
 
模板:
  1 #include <cstdio>
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <cmath>
  6 #include <queue>
  7 #define REP(i, s, n) for(int i = s; i <= n; i ++)
  8 #define RAP(i, n, s) for(int i = n; i >= s; i --)
  9 #define now ch[x][c]
 10 using namespace std;
 11 const int maxn = 400000 + 10;
 12 const int maxsig = 2;
 13 char S[10000 + 10];
 14 int n;
 15 inline void read(int &x){
 16     x = 0; int sig = 1; char ch = getchar();
 17     while(!isdigit(ch)) { if(ch == '-') sig = -1; ch = getchar(); }
 18     while(isdigit(ch)) x = 10 * x + ch - '0', ch = getchar();
 19     x *= sig; return ;
 20 }
 21 inline void write(int x){
 22     if(x == 0) { putchar('0'); return; }
 23     if(x < 0) putchar('-'), x = -x;
 24     int len = 0, buf[20];
 25     while(x) buf[len ++] = x % 10, x /= 10;
 26     RAP(i, len - 1, 0) putchar(buf[i] + '0'); return ;
 27 }
 28 namespace Aho_Corasick{
 29     int ch[maxn][maxsig], val[maxn], f[maxn], last[maxn], len[maxn], ms;
 30     void AC_init(){
 31         ms = 0;
 32         memset(ch, 0, sizeof(ch));
 33         memset(val, 0, sizeof(val));
 34         memset(f, 0, sizeof(f));
 35         memset(last, 0, sizeof(last));
 36         memset(len, 0, sizeof(len));
 37         return ;
 38     }
 39     void insert(char* s, int v){
 40         int x = 0, i;
 41         for(i = 0; s[i] != '\0'; i ++){
 42             int c = s[i] - '0'; if(!now) now = ++ ms; x = now;
 43         }
 44         val[x] = v; len[x] = i; return ;
 45     }
 46     void getfail(){
 47         queue<int> Q;
 48         REP(i, 0, maxsig - 1) if(ch[0][i]) Q.push(ch[0][i]);
 49         while(!Q.empty()){
 50             int x = Q.front(); Q.pop();
 51             REP(c, 0, maxsig - 1){
 52                 if(!now) { now = ch[f[x]][c]; continue; }
 53                 Q.push(now); int cur = f[x];
 54                 while(cur && !now) cur = f[cur];
 55                 f[now] = ch[cur][c]; last[now] = val[f[now]] ? f[now] : last[f[now]];
 56             }
 57         }
 58         return ;
 59     }
 60     void AC_print(int i, int j){
 61         if(j){
 62             write(val[j]); printf(": ");
 63             write(i - len[j] + 1); printf(" to ");
 64             write(i); putchar('\n');
 65             AC_print(i, last[j]);
 66         }
 67         return ;
 68     }
 69     void solve(char* T){
 70         int cur = 0;
 71         for(int i = 0; T[i] != '\0'; i ++){
 72             cur = ch[cur][T[i] - '0'];
 73             if(val[cur]) AC_print(i, cur);
 74             else if(last[cur]) AC_print(i, last[cur]);
 75         }
 76         return ;
 77     }
 78 }using namespace Aho_Corasick;
 79 bool init(){
 80     read(n); if(!n) return false;
 81     AC_init();
 82     REP(i, 1, n) scanf("%s", S), insert(S, i);
 83     return true;
 84 }
 85 void work(int cur){
 86     getfail();
 87     scanf("%s", S);
 88     printf("Case "); write(cur);
 89     printf(":\n");
 90     solve(S);
 91     return ;
 92 }
 93 void print(){
 94 
 95     return ;
 96 }
 97 int main(){
 98     int Case = 1;
 99     while(init()) work(Case ++);
100     return 0;
101 }

 

posted @ 2015-04-03 20:42  AI_Believer  阅读(269)  评论(0编辑  收藏  举报