【HDU 2222】Keywords Search

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

  今天学习了一下Aho-Corasick Automation。以前学了trie之后就停止搞字符串这方面了,因为今年NOI出现了AC自动机,所以要学习一下。

  这个题目的代码很多,我只是贴出来纪念一下第一道AC自动机,我也是跟别人学的。希望做的题多了,我也可以形成自己的风格(这个风格就比较符合我了)……


  加油!

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
using namespace std;

int n,Cases;
char pattern[51],match[1000001];
struct Aho_Corasick{
	struct NODE{
		int cnt;
		NODE *fail,*next[26];
		NODE(){fail=NULL,cnt=0;memset(next,0,sizeof(next));}
	}*root,*p;
	queue<NODE*> q;
	
	void init(){root=new NODE();}
	
	void build(){
		q.push(root);
		while(!q.empty()){
			NODE *cur=q.front();q.pop();
			for(int i=0;i<26;i++) 
				if(cur->next[i]){
					for(p=cur->fail;p;p=p->fail)
						if(p->next[i]){
							cur->next[i]->fail=p->next[i];
							break;
						}
					if(!p) cur->next[i]->fail=root;
					q.push(cur->next[i]);
				}
		}
	}
	
	void insert(char *s){
		int len=strlen(s);p=root;
		for(int i=0;i<len;i++){
			if(!p->next[s[i]-'a']) p->next[s[i]-'a']=new NODE();
			p=p->next[s[i]-'a'];
		}
		p->cnt++;
	}
	
	void query(char *s){
		int ans=0,len=strlen(s);p=root;
		for(int i=0;i<len;i++){
			while(!p->next[s[i]-'a'] && p!=root) p=p->fail;
			p=p->next[s[i]-'a'];
			if(!p) p=root;
			for(NODE *j=p;j&&j->cnt!=-1;j=j->fail)
				ans+=j->cnt,j->cnt=-1;
		}
		printf("%d\n",ans);
	}
}AC;

int main(){
	scanf("%d",&Cases);
	while(Cases--){
		scanf("%d",&n);
		AC.init();
		while(n--){
			scanf("%s",pattern);
			AC.insert(pattern);
		}
		AC.build();
		scanf("%s",match);
		AC.query(match);
	}
	return 0;
}
posted @ 2011-08-11 21:42  Delostik  阅读(217)  评论(0编辑  收藏  举报