Aho-Corasick automaton,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法。
AC自动机是字典树和KMP的结合。
可以解决的问题:给定多个单词,再给一个字符串,问有多少个单词在这个字符串中出现过。
这个问题可以用KMP挨个串匹配,但是如果单词数目多的话肯定会超时。
数中节点:
struct node{
node *next[26];
node *fail;
int sum;
};
sum统计以该字母结尾的单词数目。fail指针相当于KMP中的next数组。
具体可以看这篇文章,讲的不错:
http://blog.csdn.net/creatorx/article/details/71100840
题目:
HDU2222
代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <queue>
using namespace std;
const int N = 10005;
const int L1 = 52;
const int L2 = 1000005;
struct node{
node *next[26];
node *fail;
int sum;
};
node *root;
queue<node*> Q;
void init(){
root = (node*)malloc(sizeof(node));
for(int i = 0; i < 26; i++)
root->next[i] = NULL;
root->fail = NULL;
root->sum = 0;
while(!Q.empty())Q.pop();
}
void insert(char *str){
node *tmp = root, *p;
int len = strlen(str);
for(int i = 0; i < len; i++){
int x = str[i] - 'a';
if(tmp->next[x] == NULL){
p = (node*)malloc(sizeof(node));
for(int j = 0; j < 26; j++)
p->next[j] = NULL;
p->fail = NULL;
p->sum = 0;
tmp->next[x] = p;
}
tmp = tmp->next[x];
}
tmp->sum++;
}
void build(){
node *p, *tmp;
Q.push(root);
while(!Q.empty()){
tmp = Q.front();
Q.pop();
for(int i = 0; i < 26; i++){
if(tmp->next[i] == NULL) continue;
if(tmp == root){
tmp->next[i]->fail = root;
}
else{
p = tmp->fail;
while(p){
if(p->next[i]){
tmp->next[i]->fail = p->next[i];
break;
}
p = p->fail;
}
if(!p) tmp->next[i]->fail = root;
}
Q.push(tmp->next[i]);
}
}
}
int ac_automation(char *str){
int cnt = 0;
node *tmp, *p = root;
int len = strlen(str);
for(int i = 0; i < len; i++){
int x = str[i] - 'a';
while(p != root && p->next[x] == NULL)
p = p->fail;
p = p->next[x];
if(!p) p = root;
tmp = p;
while(tmp != root){
if(tmp->sum >= 0){
cnt += tmp->sum;
tmp->sum = -1;
}
else
break;
tmp = tmp->fail;
}
}
return cnt;
}
int main(){
int t, n;
char str1[L1];
char str2[L2];
scanf("%d", &t);
while(t--){
init();
scanf("%d", &n);
for(int i = 0; i < n; i++){
scanf("%s", str1);
insert(str1);
}
build();
scanf("%s", str2);
int cnt = ac_automation(str2);
printf("%d\n", cnt);
}
return 0;
}