HDU 2222 AC自动机模版

弄个模版也能花一天。。。。太佩服我自己了。。。。root的初始化都没弄好。。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#define val 10005
using namespace std;
struct Dictree
{
	int cnt;
	Dictree *fail,*next[26];
}*root;
queue<Dictree*> q;
int n,ans;
char str[val*100],s[val*100];
void build_tree();
void insert(char *,int);
void set_fail();
void ac_auto(char *);
void empty_tree(Dictree *);
int main()
{
	int t;
	for(scanf("%d",&t);t;t--)
	{
		scanf("%d",&n);
		getchar();
		build_tree();
		set_fail();
		gets(str);
		ans=0;
		ac_auto(str);
		printf("%d\n",ans);
		empty_tree(root);
	}
	return 0;
}
void build_tree()
{
	int i;
	root=(Dictree*)malloc(sizeof(Dictree));
	root->cnt=0;
	memset(root->next,NULL,sizeof(root->next));
	for(i=0;i<n;i++)
	{
		gets(s);
		insert(s,i);
	}
}
void insert(char *s,int no)
{
	int i;
	struct Dictree *p,*t;
	p=root;
	for(i=0;s[i];i++)
	{
		if(p->next[s[i]-'a']==NULL)
		{
			t=(Dictree*)malloc(sizeof(Dictree));
			memset(t->next,NULL,sizeof(t->next));
			t->cnt=0;
			t->fail=NULL;
			p->next[s[i]-'a']=t;
		}
		p=p->next[s[i]-'a'];
	}
	p->cnt++;
}
void set_fail()
{
	int i;
	Dictree *p,*temp;
	root->fail=NULL;
	q.push(root);
	while(!q.empty())
	{
		p=q.front();
		q.pop();
		for(i=0;i<26;i++)
		{
			if(p->next[i])
			{
				if(p==root) p->next[i]->fail=root;
				else
				{
					temp=p->fail;//从父亲的fail开始寻找
					while(temp)
					{
						if(temp->next[i])//儿子中没有该字母,继续寻找
						{
							p->next[i]->fail=temp->next[i];
							break;
						}
						temp=temp->fail;
					}
					if(!temp) p->next[i]->fail=root;
				}
				q.push(p->next[i]);
			}
		}
	}
}
void ac_auto(char *s)
{
	int i,index;
	Dictree *p,*temp;
	p=root;
	for(i=0;s[i];i++)
	{
		index=s[i]-'a';
		while(p!=root)
		{
			if(p->next[index]) break;
			p=p->fail;
		}
		temp=p=p->next[index];
		if(p==NULL) temp=p=root;
		while(temp)//找到了一个,继续找,但不要移动原来的位置
		{
			if(temp->cnt>=0)
			{
				ans+=temp->cnt;
				temp->cnt=-1;
			}
			else break;
			temp=temp->fail;
		}
	}
}
void empty_tree(Dictree *p)
{
	int i;
	for(i=0;i<26;i++)
		if(p->next[i])
			empty_tree(p->next[i]);
	free(p);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值