HDU 3065 病毒侵袭持续中(AC自动机)

题目链接:HDU 3065


AC自动机第二题~

模板几乎没有改动,只是模式字符串中出现了字母以外的字符需要处理一下,还有需要将计数的标记取消。

源代码

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int kind = 27;
struct node{
	node *next[kind];
	int count ;
	node* fail;
	node(){
		count = 0;
		fail = NULL;
		memset(next,0,sizeof(next));
	}
}*q[5000000];
int ans[1111];
node *root;
int head,tail;
char word[1010][55];
char str[2000010];
void insert(char *s,int k){ //构建trie
	int len = strlen(s);
	node *p = root;
	for(int i=0;i<len;i++){
		int index = s[i]-'A';
		if(!p->next[index])
			p->next[index] = new node;
		p=p->next[index];
	}
	p->count = k;
}
void build_ac_automation(){ //初始化fail指针
	q[tail++] = root;
	while(head<tail){
		node *p = q[head++];
		node *tmp = NULL;
		for(int i=0;i<kind;i++){
			if(p->next[i] != NULL){
				if(p == root)//首元素必须指根
					p->next[i]->fail = root;
				else{
					tmp =  p->fail; //失败指针(跳转指针)
					while(tmp != NULL){
						if(tmp->next[i] != NULL){//找到匹配
							p->next[i]->fail = tmp->next[i];
							break;
						} //如果没找到,则继续向上一个失败指针找
						tmp = tmp->fail;
					}
					if(tmp == NULL) //为空 则从头匹配
						p->next[i]->fail = root;
				}
				q[tail++] = p->next[i];//下一层入队
			}
		}
	}
}
void query(){
	int len = strlen(str);
	node *p = root;
	int cnt = 0;
	int index;
	for(int i=0;i<len;i++){
		if(str[i]<'A' || str[i] > 'Z')
			index = 26;
		else
			index = str[i]-'A';
		while(p->next[index] == NULL && p!=root)
			p = p->fail;
		p = p->next[index];
		if(p == NULL)
			p = root;
		node *tmp = p;//tmp 动 , p不动。
		while(tmp != root && tmp->count != 0){
			ans[tmp->count]++;
			tmp = tmp ->fail; 
		}
	}
}
void clear(node *root){
	if(!root)
		return ;
	else{
		for(int i=0;i<kind;i++)
			clear(root->next[i]);
	}
	delete(root);
}
int main(){
	int n;
	while(scanf("%d",&n)!=EOF){
		memset(ans,0,sizeof(ans));
		root = new node;
		getchar();
		for(int i=0;i<n;i++){
			gets(word[i]);
			insert(word[i],i+1);
		}
		gets(str);
		head = tail = 0;
		build_ac_automation();
		query();
		int m;
		for(int i=1;i<=n;i++){
			if(ans[i]){
				printf("%s: %d\n",word[i-1],ans[i]);
			}
		}
		clear(root);
	}
	return 0;
}


posted @ 2015-10-28 21:58  编程菌  阅读(168)  评论(0编辑  收藏  举报