HDU-3065 病毒侵襲持續中 (AC自動機)
阿新 • • 發佈:2018-11-10
https://vjudge.net/problem/HDU-3065
思路:和普通的自動機區別不大。輸入模式串的時候要注意帶空格的輸入。對於模式串中不在大寫字母範圍內的可以讓他變為‘Z’+1,這樣就可以節省空間。在進行查詢操作的時候,遇到非大寫字母不能if(.....) continue,因為這樣就相當於把非大寫字母從模式串中去掉了。對於AAA這種情況,可在字典樹中加一個cnt計數。第2個A的fail是指向第一個A的,詳情見程式碼83-88行。
#include<bits/stdc++.h> #define maxn 1005 #define N 20000005 using namespace std; char s[maxn][55]; int ans[maxn]; char pattern[N]; struct node{ node *next[27]; node *fail; int index; int cnt; node() { memset(next,NULL,sizeof(next)); fail=NULL; index=0; cnt=0; } }; node *root; void Insert(char str[],int index) { node *p=root; for(int i=0;str[i]!='\0';i++) { int id=str[i]-'A'; if(p->next[id]==NULL) p->next[id]=new node; p=p->next[id]; } p->index=index; } void build_fail_pointer() { queue<node *>Q; Q.push(root); node *temp,*p; while(!Q.empty()) { temp=Q.front();Q.pop(); for(int i=0;i<27;i++) { if(temp->next[i]!=NULL) { if(temp==root) temp->next[i]->fail=root; else { p=temp->fail; while(p) { if(p->next[i]!=NULL) { temp->next[i]->fail=p->next[i]; break; } p=p->fail; } if(p==NULL) temp->next[i]->fail=root; } Q.push(temp->next[i]); } } } } void ac_automation(char pattern[]) { node *p=root; for(int i=0;pattern[i]!='\0';i++) { if(pattern[i]<'A'||pattern[i]>'Z') pattern[i]='Z'+1; int id=pattern[i]-'A'; while(p->next[id]==NULL&&p!=root) p=p->fail; p=p->next[id]; if(p==NULL) p=root; node *temp=p; while(temp!=root) { if(temp->index!=0) { temp->cnt++; ans[temp->index]=temp->cnt; } temp=temp->fail; } } } int main() { int n; while(scanf("%d",&n)!=EOF){ memset(ans,0,sizeof(ans)); root=new node; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%s",s[i]); Insert(s[i],i); } getchar(); gets(pattern); build_fail_pointer(); ac_automation(pattern); for(int i=1;i<=n;i++) { if(ans[i]!=0) { printf("%s: %d\n",s[i],ans[i]); } } } return 0; }