HDU-2222 Keywords Search(AC自动机--模板题)

题目大意:统计一共出现了多少次模板串。

题目分析:AC自动机的模板题。不过这题有坑,相同的模板串不能只算一次。

 

代码如下:

# include<iostream>
# include<cstdio>
# include<queue>
# include<map>
# include<string>
# include<cstring>
# include<algorithm>
using namespace std;

const int N=10000;

int ch[N*50+5][26];
int val[N*50+5];
int last[N*50+5];
int f[N*50+5];
bool mark[N*50+5];
map<string,int>mp;
string str[N+5];

struct AC
{
	int cnt,res;
	void init()
	{
		res=cnt=0;
		memset(ch,0,sizeof(ch));
		memset(val,0,sizeof(val));
		memset(mark,false,sizeof(mark));
	}
	int idx(char c)
	{
		return c-'a';
	}
	void insert(string str,int v)
	{
		int u=0;
		int n=str.size();
		for(int i=0;i<n;++i){
			int c=idx(str[i]);
			if(!ch[u][c]) ch[u][c]=++cnt;
			u=ch[u][c];
		}
		val[u]=v;
	}
	void getFail()
	{
		queue<int>q;
		f[0]=0;
		for(int i=0;i<26;++i){
			int u=ch[0][i];
			if(!u) continue;
			f[u]=0;
			q.push(u);
			last[u]=0;
		}
		while(!q.empty())
		{
			int r=q.front();
			q.pop();
			for(int i=0;i<26;++i){
				int u=ch[r][i];
				if(!u){
					ch[r][i]=ch[f[r]][i];
				}else{
					q.push(u);
					int v=f[r];
					while(v&&!ch[v][i]) v=f[v];
					f[u]=ch[v][i];
					last[u]=val[f[u]]?f[u]:last[f[u]];
				}
			}
		}
	}
	void ac(string str)
	{
		int n=str.size();
		int j=0;
		for(int i=0;i<n;++i){
			int c=idx(str[i]);
			j=ch[j][c];
			if(val[j]) print(j);
			else if(last[j]) print(last[j]);
		}
	}
	void print(int u)
	{
		if(u){
			if(!mark[val[u]]) res+=mp[str[val[u]]];
			mark[val[u]]=true;
			print(last[u]);
		}
	}
	int getResult()
	{
		return res;
	}
}ac;

char s[N*100+5];

int main()
{
	int T,n;
	scanf("%d",&T);
	while(T--)
	{
		mp.clear();
		scanf("%d",&n);
		ac.init();
		for(int i=1;i<=n;++i){
			cin>>str[i];
			++mp[str[i]];
			ac.insert(str[i],i);
		}
		scanf("%s",s);
		ac.getFail();
		ac.ac(s);
		printf("%d\n",ac.getResult());
	}
	return 0;
}

  

posted @ 2016-08-09 19:39  20143605  阅读(162)  评论(0编辑  收藏  举报