2896 病毒侵襲(AC自動機模板)
病毒侵襲
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 33670 Accepted Submission(s): 7578Problem Description當太陽的光輝逐漸被月亮遮蔽,世界失去了光明,大地迎來最黑暗的時刻。。。。在這樣的時刻,人們卻異常興奮——我們能在有生之年看到500年一遇的世界奇觀,那是多麼幸福的事兒啊~~
但網路上總有那麼些網站,開始藉著民眾的好奇心,打著介紹日食的旗號,大肆傳播病毒。小t不幸成為受害者之一。小t如此生氣,他決定要把世界上所有帶病毒的網站都找出來。當然,誰都知道這是不可能的。小t卻執意要完成這不能的任務,他說:“子子孫孫無窮匱也!”(愚公後繼有人了)。
萬事開頭難,小t收集了好多病毒的特徵碼,又收集了一批詭異網站的原始碼,他想知道這些網站中哪些是有病毒的,又是帶了怎樣的病毒呢?順便還想知道他到底收集了多少帶病毒的網站。這時候他卻不知道何從下手了。所以想請大家幫幫忙。小t又是個急性子哦,所以解決問題越快越好哦~~Input
接下來N行,每行表示一個病毒特徵碼,特徵碼字串長度在20—200之間。
每個病毒都有一個編號,依此為1—N。
不同編號的病毒特徵碼不會相同。
在這之後一行,有一個整數M(1<=M<=1000),表示網站數。
接下來M行,每行表示一個網站原始碼,原始碼字串長度在7000—10000之間。
每個網站都有一個編號,依此為1—M。
以上字串中字元都是ASCII碼可見字元(不包括回車)。Output依次按如下格式輸出按網站編號從小到大輸出,帶病毒的網站編號和包含病毒編號,每行一個含毒網站資訊。
web 網站編號: 病毒編號 病毒編號 …
冒號後有一個空格,病毒編號按從小到大排列,兩個病毒編號之間用一個空格隔開,如果一個網站包含病毒,病毒數不會超過3個。
最後一行輸出統計資訊,如下格式
total: 帶病毒網站數
冒號後有一個空格。
Sample Input
#include <iostream> #include <cstring> #include <cstdio> #include <queue> using namespace std; struct Trie { int next[210*500][130], fail[210*500], end[210*500];//一維下標代表節點數 end代表了節點數,除葉子節點以外全部是-1.else是字串的ID //next的值代表子節點的編號 int root ,L;//L代表節點總數 int Newnode() { for(int i=0; i<130; i++) next[L][i] = -1; end[L++] = -1;//除了葉子節點以外全部設為-1; return L-1; } void Init() { L = 0; root = Newnode(); } void Insert(char *s, int id) { int len = strlen(s); int now = root; for(int i=0; i<len; i++) { if(next[now][s[i]] == -1) next[now][s[i]] = Newnode(); now = next[now][s[i]];//往下形成一條鏈 } end[now] = id;//葉子節點設定為該字串的編號. } void Build() { queue <int> Q; fail[root] = root; for(int i=0 ; i<130; i++) { if(next[root][i] == -1) next[root][i] = root;//如果根節點的子節點為空,那麼直接賦值為root //這樣也起到了一個類似失配指標的作用,如果 是NULL,也是失配的情況,為了提高搜尋效率也應該轉到最長字尾的節點。 else { fail[next[root][i]] = root;//第二層的節點全部反指向根節點 Q.push(next[root][i]);//第二層節點入隊 } } while(!Q.empty()) { int now = Q.front();//深搜的基本操作了,以當前節點為中心搜尋所有子節點入隊 Q.pop(); for(int i=0; i<130; i++) { if(next[now][i] == -1)// next[now][i] = next[fail[now]][i];//如果節點的子節點為空,那麼直接賦值為其失配指標指向的節點的子節點 //這樣也起到了一個類似失配指標的作用,如果 是NULL,也是失配的情況,為了提高搜尋效率也應該轉到最長字尾的節點。 //他喵的這難道不是個圖了嗎??? else { fail[next[now][i]] = next[fail[now]][i];//因為now節點作為父節點一定已經匹配了失配指標 //所以now節點的子節點的失配指標直接指向now節點的失配指標所指向的節點的子節點。 //now節點的父節點和 now指向的節點的父節點一定相等,而now和 now的子節點指向的節點的父節點一定相等, //這樣形成了一個節點所指向的節點,其兩者的父節點一定相等,這樣跳轉提高了搜尋效率。 Q.push(next[now][i]); } } } } bool used[510]; bool Query(char *buf, int n, int id) { int len = strlen(buf); int now = root; memset(used, false, sizeof(used)); bool flag = false; for(int i=0; i<len; i++) { now = next[now][buf[i]]; int tmp = now;//now要記錄當前字元的節點位置所以不能動 while(tmp != root)//這裡一直在搜尋葉子節點(即以0-i為字首(這個想法感覺比較重要)的所有可能的字串) { if(end[tmp] != -1)// !=-1說明已經到了葉子節點 { used[end[tmp]] = true; flag = true; } tmp = fail[tmp]; } } if(!flag) return false; printf("web %d:", id); for(int i=1; i<=n; i++) if(used[i]) printf(" %d",i); puts(""); return true; } } AC; char buf[10010]; int main() { int n,m; while(~scanf("%d",&n)) { AC.Init(); for(int i=1; i<=n; i++) { scanf("%s",buf); AC.Insert(buf,i); } AC.Build(); /*for (int i = 0;i < 20; i++){ cout << AC.end[i] << ' '; } cout << '\n';*/ int ans = 0; scanf("%d",&m); for(int i=1; i<=m; i++) { scanf("%s",buf); if(AC.Query(buf, n, i)) ans++; } printf("total: %d\n", ans); } return 0; }
相關推薦
2896 病毒侵襲(AC自動機模板)
病毒侵襲Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 33670 Accepted Submission(s
HDU-2896 病毒侵襲(AC自動機)
所有 build 我們 main init ane 哪些 nod class 病毒侵襲 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub
hdu 2896 病毒侵襲 AC自動機
病毒侵襲 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 20142 Accepted Submissio
HDU 2896 病毒入侵 AC自動機
病毒侵襲 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 37537  
HDU2896 病毒侵襲 AC自動機
題目大意:給出n個病毒和n個網站,找出每一個網站中含有的病毒種類,並按病毒編號升序輸出,最後統計含有病毒的網站個數。 分析:比較裸的AC自動機的題,我們可以在構造tire樹的過程中順便把編號插入,然後詢問時紀錄病毒個數的同時用一個數組紀錄病毒的編號,然後排序輸出即可(WA
HDU 2896 病毒侵襲
http app != define int public front std lag 二次聯通門 : HDU 2896 病毒侵襲 /* HDU 2896 病毒侵襲 AC自動機 此題太坑啦。。。 用
AC自動機模板
insert 自動機 mat roo oot node truct amp 字典樹 struct node { node *next[26]; node *fail; int sum; }; int cnt; node *roo
HDU3695(AC自動機模板題)
16px tdi out 模板題 getc else return typedef queue 題意:給你n個字符串,再給你一個大的字符串A,問你著n個字符串在正的A和反的A裏出現多少個? 其實就是AC自動機模板題啊( ╯□╰ ) 正著query一次再反著que
hdu 2896 病毒侵襲
search ash names accep amp mis null 包含 aaa Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi
hdu2222(ac自動機模板)
har isp truct itl color 樹節點 namespace print 好的 先推薦兩篇寫的很好的ac自動機blog: http://blog.csdn.net/creatorx/article/details/71100840 http://blog.cs
HDU 2222 Keywords Search(AC自動機模板題)
stack uil empty cst keywords cto ble ont max http://acm.hdu.edu.cn/showproblem.php?pid=2222 題意:給出多個單詞,最後再給出一個模式串,求在該模式串中包含了多少個單詞。 思路
HDU 2222 Keywords Search (AC自動機模板題)
出現 tro spa 繼續 time int cas keyword arc Keywords Search Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe
BZOJ2938 [Poi2000]病毒 【AC自動機】
格式 指向 namespace ++ getch continue c++ sca 存在 題目 二進制病毒審查委員會最近發現了如下的規律:某些確定的二進制串是病毒的代碼。如果某段代碼中不存在任何一段病毒代碼,那麽我們就稱這段代碼是安全的。現在委員會已經找出了所有的病毒代碼段
2938. [POI2000]病毒【AC自動機】
color esc mar hellip tex dash sample script 需要 Description 二進制病毒審查委員會最近發現了如下的規律:某些確定的二進制串是病毒的代碼。如果某段代碼中不存在任何一段病毒代碼,那麽我們就稱這段代碼是安全的。現在委員
洛谷P3808 & P3796 AC自動機模板
style sca %d www. ios https front query 字符 題目:P3808:https://www.luogu.org/problemnew/show/P3808 P3796:https://www.luogu.org/problemnew/sh
hdu 2222 AC自動機(模板題)
模式串 har sizeof 問題 null word 指向 pan 子節點 <題目鏈接> 題目大意: 給你一些單詞,和一個字符串,問你這個字符串中含有多少個上面的單詞。 解題分析: 這是多模匹配問題,如果用KMP的話,對每一個單詞,都跑一遍KMP,那麽當單詞數
Keywords Search HDU2222 AC自動機模板題
type pop class 都是 head gcd rds cst ons ac自動機說起來很復雜,其實和kmp是一樣的思路,都是尋找相同前後綴,減少跳的次數。只要理解了kmp是怎麽求next數組的,ac自動機bfs甚至比knp還好寫。 這裏大致說一下kmp求next數組
洛谷P2444 病毒【AC自動機】
long 字符 結果 程序 沒有 int pan 描述 恢復 題目描述 二進制病毒審查委員會最近發現了如下的規律:某些確定的二進制串是病毒的代碼。如果某段代碼中不存在任何一段病毒代碼,那麽我們就稱這段代碼是安全的。現在委員會已經找出了所有的病毒代碼段,試問,是否存在一個無限
18.10.29 躲不開的病毒(AC自動機+dfs)
ac自動機 class 都是 輸出 insert == char 特征 math.h 描述 有若幹種病毒,每種病毒的特征代碼都是一個01串。 每個程序也都是一個01串。 問是否存在不被病毒感染(不包含任何病毒的特征代碼)的無限長的程序。 輸入第一行是整數n,表示有n
洛谷2444 [POI2000]病毒(AC自動機)(DFS)
題目 二進位制病毒審查委員會最近發現瞭如下的規律:某些確定的二進位制串是病毒的程式碼。如果某段程式碼中不存在任何一段病毒程式碼,那麼我們就稱這段程式碼是安全的。現在委員會已經找出了所有的病毒程式碼段,試問,是否存在一個無限長的安全的二進位制程式碼。 示例: 例如如果{011, 11, 0