1. 程式人生 > 實用技巧 >hdu 3065 病毒侵襲持續中 (AC自動機)

hdu 3065 病毒侵襲持續中 (AC自動機)

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=3065

多測
卡記憶體

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;

const int maxn = 100100; 

int n, rt = 0, tot = 0; 
int ans[maxn];

struct Node{
	int son[30], en, fail;
}t[maxn];

char s[1010][55];
char txt[2000010];

void insert(int num){
	int p = rt;
	int len = strlen(s[num]);
	for(int i = 0 ; i < len ; ++i){
		if(!t[p].son[s[num][i] - 'A']){
			t[p].son[s[num][i] - 'A'] = ++tot;
		}
		p = t[p].son[s[num][i] - 'A'];
	} 
	t[p].en = num;
}

void build(){
	queue<int> q; 
	t[rt].fail = rt;
	for(int i = 0 ; i <= 25 ; ++i){
		if(t[rt].son[i]) q.push(t[rt].son[i]);
	}
	
	while(!q.empty()){
		int u = q.front(); q.pop();
		for(int i = 0 ; i <= 25 ; ++i){
			if(t[u].son[i]){
				t[t[u].son[i]].fail = t[t[u].fail].son[i];
				q.push(t[u].son[i]);
			} else{
				t[u].son[i] = t[t[u].fail].son[i];
			}
		}
	}
}

void query(){
	int p = rt;
	int len = strlen(txt);
	for(int i = 0 ; i < len ; ++i){
		if(txt[i] < 'A' || txt[i] > 'Z') p = 0;
		else p = t[p].son[txt[i] - 'A'];
		
		for(int j = p ; j ; j = t[j].fail) {
			++ans[t[j].en];
		}
	}
}

ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }

int main(){
	while(scanf("%d", &n) != EOF && n){
		memset(ans, 0, sizeof(ans));
		tot = 0;
		memset(t, 0, sizeof(t)); 
		for(int i = 1 ; i <= n ; ++i){
			scanf("%s", s[i]);
			insert(i);
		}
		
		build();
		
		scanf("%s", txt);
		query();
		
		for(int i = 1 ; i <= n ; ++i){
			if(ans[i]) {
				printf("%s: %d\n", s[i], ans[i]);
			}
		}
	}

	return 0;
}