一. 模板
1 struct Trie 2 { 3 int sz, M[256]; 4 int next[MAXN][50], fail[MAXN], end[MAXN]; 5 int root, L, id // L为结点个数, id为单词个数。id可选择使用 6 7 int newnode() 8 { 9 for(int i = 0; i<sz; i++) 10 next[L][i] = -1; 11 end[L++] = false; 12 return L-1; 13 } 14 15 void init(int _sz) 16 { 17 sz = _sz; 18 L = 0; 19 root = newnode(); 20 for(int i = 0; i<26; i++) //离散化 21 M['a'+i] = i; 22 } 23 24 void insert(char buf[]) 25 { 26 int len = strlen(buf); 27 int now = root; 28 for(int i = 0; i<len; i++) 29 { 30 if(next[now][M[buf[i]]] == -1) next[now][M[buf[i]]] = newnode(); 31 now = next[now][M[buf[i]]]; 32 } 33 end[now] = true; 34 } 35 void build() 36 { 37 queue<int>Q; 38 fail[root] = root; 39 for(int i = 0; i<sz; i++) 40 { 41 if(next[root][i] == -1) next[root][i] = root; 42 else fail[next[root][i]] = root, Q.push(next[root][i]); 43 } 44 while(!Q.empty()) 45 { 46 int now = Q.front(); 47 Q.pop(); 48 // end[now] |= end[fail[now]]; //此句视情况而选择 49 for(int i = 0; i<sz; i++) 50 { 51 if(next[now][i] == -1) next[now][i] = next[fail[now]][i]; 52 else fail[next[now][i]] = next[fail[now]][i], Q.push(next[now][i]); 53 } 54 } 55 } 56 57 int query(char buf[]) 58 { 59 int len = strlen(buf); 60 int now = root; 61 int res = 0; 62 for(int i = 0; i<len; i++) 63 { 64 now = next[now][M[buf[i]]]; 65 int tmp = now; 66 while(tmp != root) 67 { 68 res += end[tmp]; 69 end[tmp] = 0; 70 tmp = fail[tmp]; 71 72 } 73 } 74 return res; 75 };
二. 题目类型
1.单纯的匹配:
HDU2222 Keywords Search (出现的单词种类数)
HDU2896 病毒侵袭(出现的单词种类及其出现次数)
HDU3065 病毒侵袭持续中
ZOJ3430 Detect the Virus(需要解码)
ZOJ3228 Searching the String(分可重叠和不可重叠统计)
2.字符串(不)含有单词的统计:
POJ2278 DNA Sequence(长度为n且不含单词的字符串个数)
HDU2243 考研路茫茫——单词情结(长度小于等于n且不含单词的字符串个数)
HDU2457 DNA repair(修改原串使其不含单词)
HDU4511 小明系列故事——女友的考验
POJ1625 Censored! (需要大数)
3.字符串含有特定个单词的统计:
HDU2825 Wireless Password
4.字符串含有所有type1单词且不含type2单词的统计:
HDU3247 Resource Archiver
5.字符串长度小于等于n且价值最大的统计:
HDU2296 Ring(需要输出字符串)
三. 对AC自动机的一些浅薄的理解
1.AC自动机的结构特点:
1)前缀性:由于AC自动机是以字典树为基础的,所以插入自动机里的单词,存在前缀重叠。
2)后缀性:这是由fail[]数组决定的,当当前位置匹配失败时,匹配的指针就自动跳到与当前字符串后缀匹配最大的那个状态。
2.AC自动机中状态之间的关系:
AC自动机中,每个结点都代表着一个状态。他们之间的关系构成了一张有向图。因此,当建立好自动机之后,就可以把状态之间的关系抽出来构成一张图,然后再根据这张图进行数据统计,如路径数、最短路径之类的。