病毒侵襲 HDU - 2896 ac自動機

一、內容

 當太陽的光輝逐漸被月亮遮蔽,世界失去了光明,大地迎來最黑暗的時刻。。。。在這樣的時刻,人們卻異常興奮——我們能在有生之年看到500年一遇的世界奇觀,那是多麼幸福的事兒啊~~
但網路上總有那麼些網站,開始藉着民衆的好奇心,打着介紹日食的旗號,大肆傳播病毒。小t不幸成爲受害者之一。小t如此生氣,他決定要把世界上所有帶病毒的網站都找出來。當然,誰都知道這是不可能的。小t卻執意要完成這不能的任務,他說:“子子孫孫無窮匱也!”(愚公後繼有人了)。
萬事開頭難,小t收集了好多病毒的特徵碼,又收集了一批詭異網站的源碼,他想知道這些網站中哪些是有病毒的,又是帶了怎樣的病毒呢?順便還想知道他到底收集了多少帶病毒的網站。這時候他卻不知道何從下手了。所以想請大家幫幫忙。小t又是個急性子哦,所以解決問題越快越好哦~~

Input

第一行,一個整數N(1<=N<=500),表示病毒特徵碼的個數。
接下來N行,每行表示一個病毒特徵碼,特徵碼字符串長度在20—200之間。
每個病毒都有一個編號,依此爲1—N。
不同編號的病毒特徵碼不會相同。
在這之後一行,有一個整數M(1<=M<=1000),表示網站數。
接下來M行,每行表示一個網站源碼,源碼字符串長度在7000—10000之間。
每個網站都有一個編號,依此爲1—M。
以上字符串中字符都是ASCII碼可見字符(不包括回車)。

Output

依次按如下格式輸出按網站編號從小到大輸出,帶病毒的網站編號和包含病毒編號,每行一個含毒網站信息。
web 網站編號: 病毒編號 病毒編號 …
冒號後有一個空格,病毒編號按從小到大排列,兩個病毒編號之間用一個空格隔開,如果一個網站包含病毒,病毒數不會超過3個。
最後一行輸出統計信息,如下格式
total: 帶病毒網站數
冒號後有一個空格。

Sample Input

3
aaa
bbb
ccc
2
aaabbbccc
bbaacc

Sample Output

web 1: 1 2 3
total: 1

二、思路

  • ac自動機模板題, 注意輸入字符是ASCII碼可見字符,故範圍是0~128.

三、代碼

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int N = 505, M = 1e5 + 5, K = 60 * 205;
char s[M];
int n, tol, tr[M][130], id, cnt[M], ne[M], len;
queue<int> q;
bool use[N];
void add(int id) {
	int p = 0;
	for (int i = 0; s[i]; i++) {
		int j = s[i]; 
		if (!tr[p][j]) tr[p][j] = ++len;
		p = tr[p][j];
	} 
	cnt[p] = id; 
}
void build() { 
	for (int i = 0; i < 128; i++) {
		if (tr[0][i]) q.push(tr[0][i]);
	}
	while (!q.empty()) {
		int p = q.front(); q.pop();
		for (int j = 0; j < 128; j++) {
			int c = tr[p][j];
			if (!c) tr[p][j] = tr[ne[p]][j];
			else {
				ne[c] = tr[ne[p]][j];
				q.push(c);
			}
		}
	}
}
int main() {
	scanf("%d", &n);	
	for (int i = 1; i <= n; i++) {
		scanf("%s", s); add(i);
	}
	build();
	scanf("%d", &n);
	for (int T = 1; T <= n; T++) { 
		scanf("%s", s + 1);
		int m = strlen(s + 1);
		memset(use, false, sizeof(use));
		int ct = 0;//病毒網站個數 
		for (int i = 1, j = 0; i <= m; i++) {
			int t = s[i];
			j = tr[j][t];
			int k = j;
			while (k) {
				if (cnt[k] && !use[cnt[k]]) use[cnt[k]] = 1, ct++; 
				k = ne[k]; 
			} 
		}
		if (ct) {
			tol++; printf("web %d:", T);
			for (int i = 1; i <= 500; i++) {
				if (use[i]) printf(" %d", i);
			}
			printf("\n");
		} 
	}
	printf("total: %d\n", tol);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章