文章目錄
目標串中各個模式串出現了幾次
這就更簡單了,都不用把out標記成false了
題目中的病毒都是大寫字母這個條件應該怎麼用?
#include <cstdio>#include <cstdlib>#include <string>#include <climits>#include <iostream>#include <vector>#include <set>#include <cmath>#include <cctype>#include <algorithm>#include <sstream>#include <map>#include <cstring>#include <queue>using namespace std;//MAX_NODE = StringNumber * StringLengthconst int MAX_NODE = 50010;//節點個數,一般字元形式的題26個const int CHILD_NUM = 128;//特定題目需要char test[2000010];int cnt[1010];char vernus[1010][50];class ACAutomaton {private://每個節點的兒子,即當前節點的狀態轉移int chd[MAX_NODE][CHILD_NUM];//記錄題目給的關鍵資料int val[MAX_NODE];//傳說中的fail指標int fail[MAX_NODE];//隊列,用於廣度優先計算fail指標int Q[MAX_NODE];//字母對應的ID//int ID[128];//已使用節點個數int sz;public://初始化,計算字母對應的兒子ID,如:'a'->0 ... 'z'->25void Initialize() {fail[0] = 0;//for (int i = 0 ; i < CHILD_NUM ; i ++) {//ID[i+base] = i;//}}//重建立樹需先Resetvoid Reset() {memset(chd[0] , 0 , sizeof(chd[0]));sz = 1;}//將權值為key的字串a插入到trie中void Insert(char *a,int key) {int p = 0;for ( ; *a ; a ++) {//int c = ID[*a];int c = *a;if (!chd[p][c]) {memset(chd[sz] , 0 , sizeof(chd[sz]));val[sz] = 0;chd[p][c] = sz ++;}p = chd[p][c];}val[p] = key;}//建立AC自動機,確定每個節點的權值以及狀態轉移void Construct() {int *s = Q , *e = Q;for (int i = 0 ; i < CHILD_NUM ; i ++) {if (chd[0][i]) {fail[ chd[0][i] ] = 0;*e ++ = chd[0][i];}}while (s != e) { /*廣度優先。 關鍵*/int u = *s++;for (int i = 0 ; i < CHILD_NUM ; i ++) {int &v = chd[u][i];if (v) {*e ++ = v; /*當前結點的失敗指標 等於 父節點的失敗指標指向的結點的的同個字母兒子結點的指標*/fail[v] = chd[ fail[u] ][i]; //以下一行代碼要根據題目所給val的含義來寫//val[v] |= val[ fail[v] ];} else {v = chd[ fail[u] ][i];}}}}//解題,特定題目需要void Work(){memset(cnt, 0, sizeof(cnt));int n = strlen(test);int p = 0;for(int i = 0; i < n; i++){//int next = ID[test[i]];//if(!isupper(test[i]))//continue;int next = test[i];int tmp = p = chd[p][next];while(val[tmp] != 0){cnt[val[tmp]]++;//val[tmp] = 0; tmp = fail[tmp];}}}}AC;int main() {AC.Initialize();int n;while(scanf("%d", &n) != EOF){AC.Reset();for(int i = 1; i <= n; i++){scanf("%s", &vernus[i]);AC.Insert(vernus[i], i);}scanf("%s", test);AC.Construct();AC.Work();for(int i = 1; i <= n; i++){if(cnt[i] > 0)printf("%s: %d\n", vernus[i], cnt[i]);}}return 0;}