本题是ac--自动机模板题,详细请看下面代码注释
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <queue>
using namespace std;
const int allSon=26;
char patten[1005]; ///模式串
char text[1005]; ///文本串
int ans;
struct TrieNode
{
struct TrieNode *son[allSon];
struct TrieNode *fail;
int num;
}*root; // 一颗字典树 ,包含多个 " 单词 "
TrieNode* createNode()
{
TrieNode *p;
p = (TrieNode*)malloc(sizeof(TrieNode));
for(int i = 0; i < allSon; i++)
p->son[i] = NULL;
p->num = 0;
p->fail = NULL;
return p;
}
///插入模式串,构建字典树
void insertPatten()
{
TrieNode *p;
p = root; //建树 root 就是一个根
int index = 0;
while(patten[index] != '\0')
{
int lowercase = patten[index]-'a';
if(p->son[lowercase]==NULL) //序号代表其字母
p->son[lowercase] = createNode();
p = p->son[lowercase];
index++;
}
p->num++; //统计建成几棵树 最底下的那个节点数++
}
//求fail指针。构造AC自动机。
void build_AC_automaton() //使用队列实现每一点的fail数组
{
TrieNode *p;
p = root;
queue<TrieNode*>qu;
qu.push(p);
while(!qu.empty())
{
p = qu.front();
qu.pop();
for(int i = 0; i < allSon; i++)
{
if(p->son[i] != NULL) ///第i个孩子存在
{
if(p == root) //p是根,根节点的孩子的失败指针都指向自己
p->son[i]->fail = root;
else
{
TrieNode *node = p->fail;//找孩子的后缀,先从自己的后缀找起,因为是"树的结构 "
while(node != NULL)
{
if(node->son[i] != NULL)
{
p->son[i]->fail = node->son[i]; // i就是指向同一个字符,自然指向 下方
break;
}
node = node->fail;
}
if(node == NULL)//双亲的后缀为空,则孩子的后缀指向根
p->son[i]->fail = root;
}
qu.push(p->son[i]);//一起向下
}
}
}
}
void find_in_AC_automaton()
{
TrieNode *p;
p = root;
int index = 0;
while(text[index] != '\0')
{
int lowercase = text[index]-'a';
while(p->son[lowercase]==NULL && p!=root) //最低的节点
p = p->fail;
p = p->son[lowercase];
if(p == NULL)
p = root;
TrieNode *temp = p;
while(temp != NULL && temp->num != -1)
{
ans += temp->num; //是不是成树,sum只有0,1 是不是最后一个点
temp->num = -1; //表示该层的点是否访问过
temp = temp->fail; //该点的后缀
}
index++;
}
}
void freeNode(TrieNode *node)
{
if(node != NULL)
{
for(int i = 0; i < allSon; i++)
freeNode(node->son[i]);
}
free(node);
}
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
root = createNode();
for(int i = 0; i < n; i++)
{
scanf("%s",patten);
insertPatten();
}
scanf("%s",text);
build_AC_automaton();
ans = 0; //代表个数
find_in_AC_automaton();
printf("%d\n",ans);
freeNode(root);
}
return 0;
}