/*******************************************************題目大意:給多串病毒和一個源碼;求每串病毒在源碼中出現的次數;演算法思想:AC自動機;給每串病毒一個編號;當匹配成功後用visit數組記錄該病毒出現的次數;********************************************************/#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int K=27;const int C=55;const int N=1010;const int M=2000010;int visit[N];struct node{ node *fail; //失敗指標 node *next[K]; //Tire每個節點的26個子節點(最多26個字母) int count; //用來記錄病毒的編號 node()//建構函式初始化 { fail=NULL; count=-1; memset(next,NULL,sizeof(next)); }}*q[M]; //隊列,方便用於bfs構造失敗指標 char a[N][C]; //輸入的單詞 char str[M]; //模式串 int head,tail; //隊列的頭尾指標 void insert(char *str,node *&root,int x)//建立Trie{ if (root==NULL) root=new node; node *p=root; int len=strlen(str); for(int i=0; i<len; ++i) { int temp=str[i]-'A'; if(p->next[temp]==NULL) p->next[temp]=new node(); p=p->next[temp]; } p->count=x;}void build_ac_automation(node *root)//初始化fail指標,BFS{ root->fail=NULL; q[head++]=root;//彈出隊頭 while(head!=tail) { node *temp=q[tail++]; node *p=NULL; for(int i=0; i<K; i++) { if(temp->next[i]) { if(temp==root)//第一個元素fail必指向根 temp->next[i]->fail=root; else { p=temp->fail;//失敗指標 while(p)//2種情況結束:匹配為空白or找到匹配 { if(p->next[i])//找到匹配 { temp->next[i]->fail=p->next[i]; break; } p=p->fail; } if(p==NULL)//為空白則從頭匹配 temp->next[i]->fail=root; } q[head++]=temp->next[i];//入隊 } } }}void query(node *root,char *str)//掃描{ node *p=root;//Tire入口 int len=strlen(str); for(int i=0; i<len; i++) { int index=str[i]-'A'; if(str[i]<'A'||str[i]>'Z')//出現非大寫字母 index=26; while(p->next[index]==NULL&&p!=root)//跳轉失敗指標 p=p->fail; p=p->next[index]; if(p==NULL) p=root; node *temp=p;//p不動,temp計算尾碼串 while(temp!=root) { if(temp->count>-1)//當有出現病毒時不管之前有沒有出現過都要累加 visit[temp->count]++; temp=temp->fail; } }}int main(){ //freopen("C:\\Users\\Administrator\\Desktop\\kd.txt","r",stdin); int n; while(~scanf("%d",&n)) { memset(visit,0,sizeof(visit)); head=tail=0; node *root=NULL; for(int i=0; i<n; i++) { scanf("%s",a[i]); insert(a[i],root,i); } build_ac_automation(root); scanf("%s",str); query(root,str); for(int i=0; i<n; i++) { if(visit[i]) printf("%s: %d\n", a[i], visit[i]); } } return 0;}