AC自动机

AC自动机算法学习示例代码

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<string>
#include<queue>
string m[5]={"he", "she", "hers", "his", "is"};
string s="ahishersheishiser";

struct node
{
	node *child[26];
	node *fail;
	vector<int> exist;
	node()
	{
		fail=NULL;
		for(int i=0;i<26;i++)
		{
			child[i]=NULL;
		}
	}
};

//字典树中插入元素 
void ac_insert(node *root,int t)
{
	node *tmp=root;
	string s_now=m[t];
	for(int i=0;i<s_now.length();i++)
	{
		int c=s_now[i]-'a';
		if(tmp->child[c]==NULL)
		{
			tmp->child[c]=new node();
		}
		tmp=tmp->child[c];
	}
	tmp->exist.push_back(s_now.length());
}

void ac_build(node *root)
{
//	node *tmp=root;
	//建字典树 
	for(int i=0;i<5;i++)
	{
		ac_insert(root,i);
	}
	queue<node *> q;
	for(int i=0;i<26;i++)
	{
		if(root->child[i])
		{
			root->child[i]->fail=root;
			q.push(root->child[i]);
		}
	}
	//构建fail指针 
	while(!q.empty())
	{
		node *tmp=q.front();q.pop();
		for(int i=0;i<26;i++)
		{
			if(tmp->child[i])
			{
				node *y=tmp->child[i];
				node *fafail=tmp->fail;
				while(fafail && NULL == fafail->child[i])
					fafail=fafail->fail;
				if(fafail==NULL) y->fail=root;
				else y->fail=fafail->child[i];
				if(y->fail->exist.size())
				{
					for(int j=0;j<y->fail->exist.size();j++)
					y->exist.push_back(y->fail->exist[j]);
				}
				q.push(y);
			}
		} 
		
	}
}

void ac_print(int start,int len)
{
	for(int i=0;i<start;i++) cout<<" ";
	for(int i=start;i<start+len;i++) cout<<s[i];
	cout<<endl;
}

void ac_query(node *root)
{
	node *tmp=root;
	for(int i=0;i<s.length();i++)
	{
		int c=s[i]-'a';
		while(tmp->child[c]==NULL && tmp->fail!=NULL)
			tmp=tmp->fail;
		if(tmp->child[c]) tmp=tmp->child[c];
		else continue;
		if(tmp->exist.size())
		{
			for(int j=0;j<tmp->exist.size();j++) 
			ac_print(i+1-tmp->exist[j],tmp->exist[j]);
		}
	}
}

int main()
{
	node *root=new node();
	ac_build(root);
	cout<<s<<endl;
	ac_query(root);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值