码迷,mamicode.com
首页 > 其他好文 > 详细

HDU ACM 2222->AC自动机模版题(入门题)

时间:2015-04-24 14:24:29      阅读:127      评论:0      收藏:0      [点我收藏+]

标签:c   c++   acm   算法   ac自动机   

题意:预先给你一些单词,然后给你一个字符串,在判断有多少个单词出现在这个字符串中。

分析:使用AC自动机解决。下面是自己写的类模版。可以直接使用。最后记得释放内存。


#include<iostream>
#include<queue>
using namespace std;

#define LETTER_COUNT 26
class AC_Automation
{
private:
	struct Node
	{
		Node* fail;                  //失败指针
		Node* next[LETTER_COUNT];  //Tire树节点的子节点
		int count;                    //是否为该单词的最后一个节点
		Node()
		{
			fail=NULL;
			count=0;
			memset(next,NULL,sizeof(next));
		}
	};
	Node* m_sroot;

	void Delete(Node* p);
public:
	AC_Automation(){ m_sroot=(Node*)new Node();}
	~AC_Automation(){ Delete(m_sroot);}

	void AddWord(char* str);      //添加一个单词
	void Build_AC_Automation();
	int GetMatchingCount(char* str);
};

int AC_Automation::GetMatchingCount(char* str)
{
	int cnt=0,index;
	Node* p,*temp;

	p=m_sroot;
	while(*str)
	{
		index=*str-'a';
		while(p->next[index]==NULL && p!=m_sroot) p=p->fail;
		p=p->next[index];
		p=(p==NULL)?m_sroot:p;

		temp=p;
		while(temp!=m_sroot && temp->count!=-1)    //确保当前字符前面包含的所有单词都被匹配
		{
			cnt+=temp->count;
			temp->count=-1;
			temp=temp->fail;
		}
		str++;
	}
	return cnt;
}

void AC_Automation::Delete(Node* p)
{
	for(int i=0;i<LETTER_COUNT;i++)
		if(p->next[i]!=NULL)
			Delete(p->next[i]);
	delete p;
}

void AC_Automation::Build_AC_Automation()
{
	int i;
	Node *temp,*p;
	queue<Node*> q; //队列,用于BFS,建立失败指针

	m_sroot->fail=NULL;
	q.push(m_sroot);
	while(!q.empty())
	{
		temp=q.front();
		q.pop();
		p=NULL;
		for(i=0;i<LETTER_COUNT;i++)
		{
			if(temp->next[i]!=NULL)
			{
				if(temp==m_sroot) temp->next[i]->fail=m_sroot;
				else
				{
					p=temp->fail;
					while(p!=NULL)
					{
						if(p->next[i]!=NULL)
						{
							temp->next[i]->fail=p->next[i];
							break;
						}
						p=p->fail;
					}
					if(p==NULL) temp->next[i]->fail=m_sroot;
				}
				q.push(temp->next[i]);        //子节点如队列
			}
		}
	}
}

void AC_Automation::AddWord(char* str)
{
	Node* p=m_sroot;
	int i=0;
	int index;

	while(*str)
	{
		index=*str-'a';
		if(p->next[index]==NULL) p->next[index]=(Node*)new Node();
		p=p->next[index];
		str++;
	}
	p->count++;             //单词的最后一个节点加1,单表新加入一个单词
}

int main()
{
	int T,N,i;
	char a[51];
	char b[1000001];

	cin>>T;
	while(T--)
	{
		AC_Automation ac_auto;
		cin>>N;
		for(i=0;i<N;i++)
		{
			cin>>a;
			ac_auto.AddWord(a);
		}
		ac_auto.Build_AC_Automation();
		cin>>b;
		cout<<ac_auto.GetMatchingCount(b)<<endl;
	}
	return 0;
}


HDU ACM 2222->AC自动机模版题(入门题)

标签:c   c++   acm   算法   ac自动机   

原文地址:http://blog.csdn.net/a809146548/article/details/45244831

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!