题目:点击打开题目链接
题意:多组测试样例,每组测试样例给你n个单词和一句话,问这n个单词有多少个可以在这句话中匹配的到,即n个单词中有哪些可以在这句话中找到。
思路:AC自动机的模板题
My DaiMa:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<malloc.h>
using namespace std;
const int allson = 26;///此题中只用到了26个小写字母
char patten[60];///模式串
char text[1000005];///文本串
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;
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++;///单词末尾字符的num赋值为1,表示以它为结尾的字符串的单词数为1
}
/* 构建AC自动机,计算fail指针*/
void build_AC_automaton()
{
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)///儿子节点存在
{
if(p == root)///根节点下的儿子的fail指针都指向root
p ->son[i]->fail = root;
else///其他的儿子的fail指针就是找父亲的fail指针下有没有跟儿子相同的字符
{
TrieNode *node = p->fail;
while(node != NULL)
{
if(node ->son[i] != NULL)///有的话,就指向父亲的fail指针下的儿子节点
{
p->son[i]->fail = node->son[i];
break;
}
node = node->fail;
}
if(node == NULL)///没有的话就指向root
p->son[i]->fail = root;
}
qu.push(p->son[i]);
}
}
}
}
/*根据文本串遍历AC自动机,查找出现多少个单词*/
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;///失配之后,转到fail指针的地方再尝试进行匹配
p = p->son[lowercase];
if(p == NULL) p = root;
TrieNode *temp = p;
while(temp != NULL && temp ->num != 0)///匹配成功时还需看看fail指针处是否也含有一个单词
{
ans += temp->num;
temp ->num = 0;
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);
}
}