【HDU2222】【Keywords Search】AC自动机,有详细注释题解。

题意:给定N个单词,和一个字符串S,求这N个单词在字符串S中,有多少个出现过。

题解:AC自动机裸题一枚。


AC自动机是基于字典树的一种KMP思想高级算法,用于多字串匹配。就是把字典树建好,然后模仿KMP的前缀数组“pre[]”,在字典树内处理了一个fail(失败指针),失配时顺着往前找,并寄托于此以得到答案。


直接附代码,里面有详解。(数组模拟版!!!指针神马的都去回收站吧!)


结构体+注释版本:

#include 
#include 
#include 
#include 
#define N 250010/*HDU上实际数据范围略小,正常应该开50W*/
#define M 26/*26个字母*/
using namespace std;

struct Trie/*字典树节点结构体*/
{
	int next[M],fail;/*fail,失败指针*/
	short cnt;/*当前节点是多少个单词的结尾*/
}trie[N];

int root,cnt,ans,n;/*根默认为0*/
char t[60],s[1001000];/*t是用于建树的临时输入数组*/

int i,u,v,temp,alp,star;/*此处全为临时变量*/

void init()/*每组测试数据要清一下!*/
{
	root=cnt=ans=0;
	memset(trie,0,sizeof(trie));
}
void insert()/*建字典树*/
{
	scanf("%s",t+1);/*字典树建树过程不赘述了*/
	for(temp=root,i=1;t[i];i++)
	{
		alp=t[i]-'a';/*当前枚举到字母转化成数字*/
		if(!trie[temp].next[alp])trie[temp].next[alp]=++cnt;
		temp=trie[temp].next[alp];
	}
	trie[temp].cnt++;
}
queueq;
void acauto()/*处理出失败指针*/
{
	while(!q.empty())q.pop();
	/*(在函数内开队列,貌似就不需要清,就能省下时间,
			但是退出时系统是一定会清掉这些数据的,所以反而要慢。)*/
	q.push(root);
	while(!q.empty())
	{
		u=q.front();q.pop();
		for(i=0;i

结构体无注释版:

#include 
#include 
#include 
#include 
#define N 250010
#define M 26
using namespace std;

struct Trie
{
	int next[26],fail;
	short cnt;
}trie[N];

int root,cnt,ans,n;
char t[60],s[1001000];

int i,u,v,temp,alp,star;

void init()
{
	root=cnt=ans=0;
	memset(trie,0,sizeof(trie));
}
void insert()
{
	scanf("%s",t+1);
	for(temp=root,i=1;t[i];i++)
	{
		alp=t[i]-'a';
		if(!trie[temp].next[alp])trie[temp].next[alp]=++cnt;
		temp=trie[temp].next[alp];
	}
	trie[temp].cnt++;
}
queueq;
void acauto()
{
	while(!q.empty())q.pop();
	q.push(root);
	while(!q.empty())
	{
		u=q.front();q.pop();
		for(i=0;i

数组模拟结构体无注释版(代码短,就是短):

#include 
#include 
#include 
#include 
#define N 250010
#define M 26
using namespace std;

int next[N][26],fail[N];
short cnt[N];

int root,num,ans,n;
char t[60],s[1001000];

int i,u,v,temp,alp,star;

void init()
{
	root=num=ans=0;
	memset(fail,0,sizeof(fail));
	memset(cnt,0,sizeof(cnt));
}
void insert()
{
	scanf("%s",t+1);
	for(temp=root,i=1;t[i];i++)
	{
		alp=t[i]-'a';
		if(!next[temp][alp])next[temp][alp]=++num;
		temp=next[temp][alp];
	}
	cnt[temp]++;
}
queueq;
void acauto()
{
	while(!q.empty())q.pop();
	q.push(root);
	while(!q.empty())
	{
		u=q.front();q.pop();
		for(i=0;i








你可能感兴趣的:(AC自动机,模板)