您的位置:首页 > 其它

(AC自动机)模板

2017-08-22 17:20 302 查看
#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()//创建Tiree树并且完成对树的初始化
{
TrieNode *p;
p = (TrieNode*)malloc(sizeof(TrieNode));
memset(p->son,0,sizeof(p->son));
p->num = 0;
p->fail = NULL;
return p;
}
///插入模式串,构建字典树
void insertPatten()
{
TrieNode *p;
p = root;
int index = 0;
while(patten[index])
{
int lowercase = patten[index]-'a';
if(p->son[lowercase]==NULL)
{
p->son[lowercase] = createNode();
}
p = p->son[lowercase];
index++;
}
p->num++;//到了单词的末尾 此时是一个单词则num置一
}
///求fail指针。构造AC自动机。
void build_AC_automaton()//利用bfs构建失败指针 构建失败指针时需要注意对第二层进行处理 就是让第二层全部都指向根节点 让根节点的失败指针置为ULL
{
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;//如果node不为空 并且在node的儿子里也有字母z让这个失败指针指向失败指针的儿子
while(node != NULL)
{
if(node->son[i]!=NULL)
{
p->son[i]->fail = node->son[i];
break;
}
node = node->fail;
}
if(node == NULL)//如果到最后都没有找到node里面有字母z则直接让这个失败指针指向其root
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();
ans = 0;
find_in_AC_automaton();
printf("%d\n",ans);
freeNode(root);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: