首先,AC自动机不是Accept自动机,别以为把这段代码复制到OJ上就全都自动AC了……
其实这玩意是Aho-Corasick 造出来的,所以你懂的。
那么这玩意能干嘛咧?
•字符串的匹配问题
•多串的匹配问题※
看不懂吧?解释一下:
例如给几个单词 acbs,asf,dsef,再给出一个 很长的文章,acbsdfgeasf,问在这个文章中,总共出现了多少个单词,或者是单词出现的总次数。
怎么实现的呢,就是KMP+trie树。是以KMP为算法基础,trie为索引结构的东东。那它如何与kmp联系在一起?
•关键是在trie树上加了一种fail指针。
•Fail指针的用途:就像是kmp中的next的数组。
在字符串失配的时候确定转移的节点。AC难点就是指针的算法,看下面这么多图:
模板:
1 struct Aho_Corasick{ 2 int ch[maxn][Sigc], ms; 3 int val[maxn], f[maxn], len[maxn]; 4 int last[maxn]; 5 Aho_Corasick(){} 6 void init(){ 7 ms = 0; 8 memset(val, 0, sizeof(val)); 9 memset(ch, 0, sizeof(ch)); 10 memset(f, 0, sizeof(f)); 11 memset(last, 0, sizeof(last)); 12 memset(len, 0, sizeof(len)); 13 return ; 14 } 15 void insert(char* s, int v){ 16 int cur = 0, i; 17 for(i = 0; s[i] != ‘\0‘; i ++){ 18 int c = s[i] - ‘0‘; 19 if(!ch[cur][c]) ch[cur][c] = ++ ms; // 1 20 cur = ch[cur][c]; 21 } 22 val[cur] = v; len[cur] = i; 23 return ; 24 } 25 void make_fail(){ 26 queue<int> Q; 27 for(int i = 0; i < Sigc; i ++) if(ch[0][i]) Q.push(ch[0][i]); 28 while(!Q.empty()){ 29 int x = Q.front(); Q.pop(); 30 for(int c = 0; c < 2; c ++){ 31 int v = ch[x][c]; 32 if(!v) { ch[x][c] = ch[f[x]][c]; continue; } 33 Q.push(v); 34 int cur = f[x]; 35 while(cur && !ch[cur][c]) cur = f[cur]; 36 f[v] = ch[cur][c]; 37 last[v] = val[f[v]] ? f[v] : last[f[v]]; 38 } 39 } 40 return ; 41 } 42 };
时间: 2024-10-27 01:13:16