看了这些博客后,自己写的代码.
http://www.cppblog.com/mythit/archive/2009/04/21/80633.html
http://apps.hi.baidu.com/share/detail/16394130
http://apps.hi.baidu.com/share/detail/16394130
http://www.notonlysuccess.com/index.php/aho-corasick-automation/
题目在这:
http://acm.hdu.edu.cn/showproblem.php?pid=2222
代码在这:
#include <cstdio>
#include <cstring>
const int MAX = 10000*50;//最大的节点个数
const int M = 26;//26个小谢字母
const int fail = 27;//trie数组中的27号位存下该节点失败后走去哪个节点
const int isword = 26;//trie数组中的26号位存下该节点是否是一个单词
const int root = 0;//根的编号为0
const char a = 'a';
int trie[MAX][M+2];//trie数组
char str[MAX];//构造用的字符串
int q[MAX];//队列
int num;//给每个节点的编号
void inSert()//插入字符串
{
int i = 0;
int k = root;//从根节点开始
while (str[i]) {//走到字符串结尾
int t = str[i] - a;//转换成数字标号
if (trie[k][t] == 0){//假如还没这个节点
memset(trie[num],0,sizeof(trie[num]));//申请这个节点
trie[k][t] = num;//k进行t匹配到这个新的节点
++num;//编号++
}//假如有了,就不用申请新的节点了.
k = trie[k][t];//顺着节点走
++i;//字符串下一个字母
}
++trie[k][isword];//插完这个字符串后,最后一个节点的的isword置真,用于以后统计出现次数
}
void builtAC()//构建AC自动机
{
int s = 0;
int e = 0;
for (int i = 0; i < M; ++i) {//根节点进行扩展
if (trie[root][i]) {//存在这个转移
int v = trie[root][i];
q[e] = v;//进队列
++e;
trie[v][fail] = root;//根节点的全部儿子的失败指针指向root
}
}
while (s < e){//BFS
int t = q[s];//被扩展的节点
for (int i = 0; i < M; ++i) {
if(trie[t][i]) {//扩展出的节点
int v = trie[t][i];
q[e] = v;//进队列
++e;
int p = trie[t][fail];//被扩展节点的失败指针
while (p && trie[p][i] == 0) {//不停的沿着失败指针往root走
p = trie[p][fail];//直到走到有一个能进行转移或者走到root
}
trie[v][fail] = trie[p][i];//扩展出的节点的失败指针
}
}
++s;
}
}
int query()
{
int sum = 0;
int i = 0;
int p = root;
while (str[i]) {
int t = str[i]-a;
while (trie[p][t] == 0 && p) {//一直找到有个能进行p到t的匹配或者到根
p = trie[p][fail];
}
p = trie[p][t];//能进行匹配或者到跟
int pp = p;//pp用来查找一遍是否存在完整的单词
while (pp && trie[pp][isword] != -1) {//没到根或者没被赋值成负过
sum += trie[pp][isword];//如果是一个单词就累加
trie[pp][isword] = -1;//然后赋值成负的.这样可以加快查找.
pp = trie[pp][fail];//pp沿着fail一直往root走
}
++i;
}
return sum;
}
int main()
{
int t;
scanf("%d",&t);
while (t--) {
int n;
scanf("%d",&n);
memset(trie[root],0,sizeof(trie[root]));
num = 1;
for (int i = 0; i < n; ++i) {
scanf("%s",str);
inSert();
}
builtAC();
scanf("%s",str);
int ans = query();
printf("%d\n",ans);
}
return 0;
}