您的位置:首页 > 其它

HDU 2222:Keywords Search(AC自动机入门题)

2017-08-15 20:54 357 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222

AC自动机裸题,题目直接说的就是多模式匹配,给出多个模式串一个文本串,看模式串在文本串

中出现了多少个,AC自动机的模板题目。

AC代码:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <queue>

using namespace std;

const int allSon=26;
char patten[60]; ///模式串
char text[1000010]; ///文本串
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++;
}
///求fail指针。构造AC自动机。
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) ///第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];
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;
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(); ///构建AC自动机
ans = 0;
find_in_AC_automaton(); ///多模式匹配
printf("%d\n",ans);
freeNode(root); ///释放内存
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: