[hdu2222] Keywords Search

Description

给定 \(n\) 个长度不超过 \(50\) 的由小写英文字母组成的单词准备查询,以及一篇长为 \(m\) 的文章,问:文中出现了多少个待查询的单词。多组数据。

Input

第一行一个整数 \(T\),表示数据组数;
对于每组数据,第一行一个整数 \(n\),接下去 \(n\) 行表示 \(n\) 个单词,最后一行输入一个字符串,表示文章。

Output

对于每组数据,输出一个数,表示文中出现了多少个待查询的单词。

Sample Input

1
5
she
he
say
shr
her
yasherhs

Sample Output

3

Hint

对于全部数据,\(1\le n\le 10^4,1\le m\le 10^6\)

题解

AC自动机模板题

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<bitset>
#include<vector>
#include<iomanip>
using namespace std;

const int Size=26,Maxn=500005;
struct Trie{
	int son[Maxn][Size],fail[Maxn],cnt[Maxn];
/*	son[i][j]存放 父节点的下标为i 的子节点字符为j的下标
	fail[i]下标为i的节点如果失配放回的下标
	cnt[i]从根节点到下标为i的节点所构成的模式串的个数
*/	int id;
	Trie(){id=0;}//构造函数
	int Newnode()//新建一个节点
	{
		for(int i=0;i<Size;++i) son[id][i]=-1;
		cnt[id]=0;
		return id++;
	}
	void Init()//初始化
	{
		id=0,Newnode();
	}
	void Insert(char s[])//把模式串s插入到Trie树
	{
		int l=strlen(s),now=0,k;
		for(int i=0;i<l;++i)
		{
			k=s[i]-'a';
			if(son[now][k]==-1) son[now][k]=Newnode();
			now=son[now][k];
		}
		++cnt[now];
	}
	queue<int> Q;
	void Build()//构建Fail指针
	{
		while(!Q.empty()) Q.pop();
		fail[0]=0;
		for(int i=0;i<Size;++i)
			if(son[0][i]==-1) son[0][i]=0;
			else
			{
				fail[son[0][i]]=0;
				Q.push(son[0][i]);
			}
		int now;
		while(!Q.empty())
		{
			now=Q.front(); Q.pop();
			for(int i=0;i<Size;++i)
				if(son[now][i]==-1) son[now][i]=son[fail[now]][i];
				else
				{
					fail[son[now][i]]=son[fail[now]][i];
					Q.push(son[now][i]);
				}
		}
	}
	int Query(char s[])//文本串来匹配
	{
		int len=strlen(s),now=0,Res=0;
		for(int i=0;i<len;++i)
		{
			now=son[now][s[i]-'a'];
			int tmp=now;
			while((tmp)&&(cnt[tmp]!=-1))
			{
				Res+=cnt[tmp],
				cnt[tmp]=-1,
				tmp=fail[tmp];
			}
		}
		return Res;
	}
}AC;
char s[Maxn+Maxn];

int main()
{
	int T,n;
	for(scanf("%d",&T);T;--T)
	{
		scanf("%d",&n);
		AC.Init();
		for(int i=1;i<=n;++i)
		{
			scanf("%s",s);
			AC.Insert(s);
		}
		AC.Build();
		scanf("%s",s);
		printf("%d\n",AC.Query(s));
	}
	return 0;
}
posted @ 2020-05-02 15:37  OItby  阅读(201)  评论(0编辑  收藏  举报