hdu 2896 病毒侵袭 AC自动机

http://acm.hdu.edu.cn/showproblem.php?pid=2896

题意:给你N个匹配串和M个模式串, 问你每个模式串中,N个匹配串有哪些出现过。

思路:AC自动机,和hdu2222思路其实是一样的,只不过这里就是需要增加一个域,来标记以该结点结束的串

#include<stdio.h>
#include<string.h>
const int MAXN = 200*500+10 ;

int N , M ;
char name[210] ;
struct Node{
	int num ;		//标记这个单词的标号 
	int f ;			//表示是否是一个单词的结束 
	Node *fail ;
	Node *next[128] ;
	Node(){
		num = 0 ;
		f = 0 ;
		fail = NULL ;
		memset(next,  0 , sizeof(next)); 
	}
}*root ;
int front, rear ;
Node *que[MAXN] ;
char str[10010] ;

void build_trie(char *ch , int num){
	Node *loc = root ,*q;
	int idx ;
	for(int i=0;ch[i]!=0;i++){
		idx = ch[i] ;
		if(loc->next[idx] == NULL){
			q = new Node ;
			loc->next[idx] = q ;
		}	
		loc = loc->next[idx] ;
	}
	loc->f = 1 ;
	loc->num = num ;
}
void build_automation(){
	front = rear = 0 ;
	Node *temp ,*q ;
	root->fail = NULL ;
	que[rear++] = root ;
	
	while(front != rear){
		temp = que[front++] ;
		for(int i=0;i<128;i++){
			if(temp->next[i] == NULL)	continue ;
			if(temp == root){
				temp->next[i]->fail = root ;
			}
			else{
				q = temp->fail;
				while(q != NULL){
					if(q->next[i] != NULL){
						temp->next[i]->fail = q->next[i] ;
						break ;
					}
					q = q->fail;	
				}
				if(q == NULL)
					temp->next[i]->fail = root ;
			}
			que[rear++] = temp->next[i] ;	
		}	
	}
}
bool one[510] ;

void query(char *ch){
	Node *loc = root ,*q;
	int idx;
	for(int i=0;ch[i]!=0;i++){
		idx = str[i] ;
		while(loc!=root && loc->next[idx]==NULL)	loc=loc->fail;
		loc = loc->next[idx] ;
		if(loc == NULL){
			loc = root ;
		}
		q = loc ;
		while(q != root){
			if(q->f){
				one[ q->num] = 1 ;
			}
			q = q->fail;
		}
	}	
}
int main(){
	while(scanf("%d",&N) == 1){
		root = new Node ;
		for(int i=1;i<=N;i++){
			scanf("%s",name);
			build_trie(name , i) ;
		}
		build_automation(); 
		scanf("%d",&M);
		int res = 0 ;
		for(int i=1;i<=M;i++){
			scanf("%s",str);
			memset(one , 0 , sizeof(one));
			query(str);
			bool have = 0 ;
			for(int j=1;j<=N;j++){
				if( one[j] ){
					have = 1 ; break ;
				}
			}
			if(have){
				res++ ;
				printf("web %d:",i);
				for(int j=1;j<=N;j++){
					if( one[j] )	printf(" %d",j);
				}
				printf("\n");
			}
		}
		printf("total: %d\n",res);
	}	
	return 0 ;
}

的标号。

代码:


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值