【hdu2222】【AC自动机】Keywords Search

16 篇文章 0 订阅
5 篇文章 0 订阅

第一道AC自动机题目,这道题是模板题,唯一需要注意的是模式串可能会重复,所以需要累加。

代码:

#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 10000 * 50 + 100;
const int max_node = 1000000 + 10;
const int child_num = 26;
const int max_word = 50 + 10;
class ACAutumaton
{
private:
	int chd[maxn][child_num];
	int fail[maxn],val[maxn];
	int Q[maxn];
	int ID[128];
	int sz;
public:
	void Initialize()
	{
		fail[0] = 0;
		for(int i = 0;i < child_num;i++)
		{
			ID[i + 'a'] = i;
		}
	}
	void Reset()
	{
		memset(chd[0],0,sizeof(chd[0]));
		sz = 1;
	}
	void Insert(char *a,int key)
	{
		int p = 0;
		for(;*a ;a++)
		{
			int c = ID[*a];
			if(!chd[p][c])
			{
				memset(chd[sz],0,sizeof(chd[sz]));
				val[sz] = 0;
				chd[p][c] = sz++;
			}
			p = chd[p][c];
		}
		val[p] += key;
	}
	void Construct()
	{
		int *s = Q,*e = Q;
		for(int i = 0;i < child_num;i++)
		{
			if(chd[0][i])
			{
				fail[ chd[0][i] ] = 0;
				*e ++ = chd[0][i];
			}
		}
		while(s != e)
		{
			int u = *s++;
			for(int i = 0;i < child_num;i++)
			{
				int &v = chd[u][i];
				if(v)
				{
					*e ++ = v;
					fail[v] = chd[ fail[u] ][i];
				}
				else v = chd[ fail[u] ][i];
			}
		}
	}
	int work(char *T)
	{
		int n = strlen(T);
		int x = 0,ans = 0;
		for(int i = 0;i < n;i++)
		{
			x = chd[x][ID[T[i]]];
			int tmp = x;
			while(tmp && val[tmp] != -1)
			{
				ans += val[tmp];
				val[tmp] = -1;
				tmp = fail[tmp];
			}
		}
		return ans;
	}
}AC;
int n,T;
char temp[max_word],exp[max_node];
void init()
{
	freopen("hdu2222.in","r",stdin);
	freopen("hdu2222.out","w",stdout);
}

void readdata()
{
	AC.Initialize();
	scanf("%d",&T);
	while(T--)
	{
		AC.Reset();
		scanf("%d",&n);
		for(int i = 1;i <= n;i++)
		{
			scanf("%s",temp);
			AC.Insert(temp,1);
		}
		AC.Construct();
		scanf("%s",exp);
		printf("%d\n",AC.work(exp));
	}
}

int main()
{
	init();
	readdata();
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值