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

版权声明:转载请注明出处 https://blog.csdn.net/weixin_42557561/article/details/85384603

传送门

Analysis

AC自动机板题

注意两点
1 多组数据(虽然题目没有说)
2 文本串里会有非大写字母的字符,要注意判断

Code
#include<bits/stdc++.h>
using namespace std;
char st[8000000],ch[2000][80];
int n,tot=1,ans[1009];
struct node{
	int trans[26],fail,cnt,idx;
	void init(){
		fail=cnt=idx=0;
		memset(trans,0,sizeof(trans));
	}
}trie[2000*50];
inline void insert(int id){
	int len=strlen(ch[id]),p=1;
	for(int i=0;i<len;++i){
		int c=ch[id][i]-'A';
		if(!trie[p].trans[c]) trie[trie[p].trans[c]=++tot].init();
		p=trie[p].trans[c];
	}
	trie[p].idx=id;
}
inline void buildfail(){
	for(int i=0;i<26;++i) trie[0].trans[i]=1;
	queue<int> q;q.push(1);
	int v,w;
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=0;i<26;++i){
			v=trie[u].fail;
			while(!trie[v].trans[i]) v=trie[v].fail;
			v=trie[v].trans[i];w=trie[u].trans[i];
			if(w) trie[w].fail=v,q.push(w);
			else trie[u].trans[i]=v;
		}
	}
}
int main(){
	while(scanf("%d",&n)!=EOF)
	{		
		trie[tot=1].init();
		for(int i=1;i<=n;++i){
			scanf("%s",ch[i]);
			insert(i);
		}
		buildfail();
		scanf("%s",st);
		int tmp,len=strlen(st),now=1;
		memset(ans,0,sizeof(ans));
		for(int i=0;i<len;++i){
			if(st[i]<'A'||st[i]>'Z') {	now=1;continue;	}
			now=trie[now].trans[st[i]-'A'];
			tmp=now;
			while(tmp){
				if(trie[tmp].idx) {
					trie[tmp].cnt++;
					ans[trie[tmp].idx]++;
				}
				tmp=trie[tmp].fail;
			}
		}
		for(int i=1;i<=n;++i)
			if(ans[i]) printf("%s: %d\n",ch[i],ans[i]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42557561/article/details/85384603