您的位置:首页 > 其它

hdu2222 ac自动机模板

2014-08-09 01:40 363 查看
题意:给出一系列字符串作为关键字,再给出一个字符串作为查询串,问查询串里包含多少关键字。

字符串匹配有kmp,保存大量字符串有字典树,所以当出现大量字符串需要匹配的情况,就有了ac自动机,这名字总让人想到一种很美好的歧义。。

就是数据插入字典树,构造自动机和把字符串放进去匹配三个基本操作把。

构造自动机规则如下:

如果某个节点的父节点就是根节点,那么这个节点的失败节点也就是根节点。

如果C的子节点中,有与A相同的节点B,则A的失败节点就是B

如果C的子节点中,没有与A相同的节点,且C就是根节点,则A的失败节点就是C

如果C的子节点中,没有与A相同的节点,但C不是根节点,则令C为C的失败节点,重复

查询规则如下:

在查找时,当前处在某个节点,往下无路可走时,那么就可以沿着fail指针跳到失败节点。

如果失败节点也无路可走,则跳到失败节点的失败节点,直至有路可走或者走到根节点为止。

思路就那么回事,真要写就纠结了。。

模板代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;
const int maxn = 500010;
char str[1000010];

struct ACAutomaton{
int next[maxn][26],fail[maxn],flag[maxn],last[maxn];
int num,root;
int newnode()
{
memset(next[num],0,sizeof(next[num]));
flag[num] = 0;
return num++;//每次都加,故num为结点数
}

void init()
{
num = 0;
root = newnode();
}

void insert(char *str)
{
int len = strlen(str);
int now = root;
for(int i = 0;i < len;i++)
{
int &tmp = next[now][str[i]-'a'];//&取地址
if(!tmp)
tmp = newnode();//是空的那新建结点
now = tmp;
}
flag[now]++;
}

void getfail()
{
queue<int> q;
fail[root] = root;
for(int i = 0;i < 26;i++)
{
int u = next[root][i];
if(u)//头
{
fail[u] = last[u] = 0;
q.push(u);
}
}
while(!q.empty())
{
int now = q.front();q.pop();
for(int i = 0;i < 26;i++)
{
int u = next[now][i];
if(!u)
//这个点的第i个儿子指向now的失败节点的第i个儿子
next[now][i] = next[fail[now]][i];
else
{
fail[u] = next[fail[now]][i];//u的失败节点指向fail[now]的第i个儿子
last[u] = flag[fail[u]] ? fail[u]:last[fail[u]];//后缀链接
q.push(u);
}
}
}
}

int query(char *str){
int len = strlen(str);
int now = root;
int ret = 0;
for(int i = 0;i < len;i++)
{
now = next[now][str[i]-'a'];
int tmp = now;
while(tmp != root && flag[tmp])
{
ret += flag[tmp];
flag[tmp] = 0;//防止重复统计
tmp = last[tmp];
}
}
return ret;
}
}ac;

int main(){
int k,n;
scanf("%d",&k);
while(k--)
{
ac.init();
scanf("%d",&n);
for(int i = 0;i < n;i++)
{
scanf("%s",str);
ac.insert(str);
}
ac.getfail();//类似kmp里的next
scanf("%s",str);
printf("%d\n",ac.query(str));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: