暑假- ac自动机-(C - 病毒侵袭持续中)

明明题目没有说多组数据, 然后我就当作一组数据来做了。

看来看去代码都没有错,但是一提交就WA,害我该了一个下午。天啊!

去找题解才知道是多组数据。不要被省略”有多组数据“而欺骗了。

/* 
题意:中文题,详见HDU 3065 
思路:套AC自动机模板。 
注意:建trie树时,字符串的信息(病毒编号)存放在最后一个字母的 
value中,病毒特征码只包含“英文大写字符”,所以孩子节点只需26个
没遇到一种病毒,则把(病毒出现次数的)数组对应的值+1。
*/ 
#include<iostream>
#include<cstring>
#include<queue>
#include<ctype.h>
using namespace std;
const int MAXM=2000100;//网站长度
const int MAXN=50010;//病毒最多的需要的节点数
char web[MAXM];//网站串
char virus[1010][55];//病毒存放的数组
int virusN[1010];//对应位置病毒出现的次数
struct trie
{
	int root,trieN;//根节点和当前树的最大节点
	int child[MAXN][26],value[MAXN],fail[MAXN];//孩子节点,节点值,失配数组
	int NewTrie()//新建节点
	{
		value[trieN]=0;
		memset(child[trieN],-1,sizeof(child[trieN]));
		return trieN++;
	}
	void init()//初始化
	{
		trieN=0;
		root=NewTrie();
	}
	void Insert(char s[],int k)//建树
	{
		int x=root;
		for(int i=0;s[i];i++)
		{
			if(child[x][s[i]-'A']==-1)
			{
				child[x][s[i]-'A']=NewTrie();
			}
			x=child[x][s[i]-'A'];
		}
		value[x]=k;//对应信息存放到最后一个字母中
	}
	void Build()//构建fail数组
	{
		int x;
		queue<int> q;
		fail[root]=root;
		for(int i=0;i<26;i++)
		{
			if(child[root][i]==-1)
			{
				child[root][i]=root;
			}
			else
			{
				fail[child[root][i]]=root;
				q.push(child[root][i]);
			}
		}
		while(!q.empty())
		{
			x=q.front();q.pop();
			for(int i=0;i<26;i++)
			{
				if(child[x][i]==-1)
				{
					child[x][i]=child[fail[x]][i];
				}
				else
				{
					fail[child[x][i]]=child[fail[x]][i];
					q.push(child[x][i]);
				}
			}
		}
	}
	void query(char s[])//网站匹配
	{
		int x=root,temp;
		for(int i=0;web[i];i++)
		{
			if(!isupper(web[i]))//因为网站中字符都是ASCII码可见字符,而
			{                   //病毒只有大写字母,所以如果不是大写字母则
				x=0;            //可忽略,也可预处理先把web里面非大写字母去掉
				continue;
			}
			x=temp=child[x][s[i]-'A'];
			while(temp!=root)
			{
				if(value[temp])//存在这种病毒
				{
					virusN[value[temp]]++;//对应位置+1
				}
				temp=fail[temp];
			}
		}
	}
}ac;
int main()
{
	int n;
	while(cin>>n)
	{
		ac.init();//初始化
		memset(virusN,0,sizeof(virusN));
		for(int i=1;i<=n;i++)
		{
			cin>>virus[i];
			ac.Insert(virus[i],i);//建树
		}
		ac.Build();//构造fail
		getchar();
		cin.getline(web,MAXM);//输入网站,可能包含空格等
		ac.query(web);//匹配
		for(int i=1;i<=n;i++)
		{
			if(virusN[i])//初始为0,只要出现过这种病毒则>0
			{
				cout<<virus[i];
				cout<<": "<<virusN[i]<<endl;
			}
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值