【Trie图】BZOJ3940-[Usaco2015 Feb]Censoring
【题目大意】
有一个匹配串和多个模式串,现在不断删去匹配串中的模式串,求出最后匹配串剩下的部分。
【思路】
众所周知,KMP的题往往对应着一道AC自动机quq。本题同BZOJ3942(KMP),这里改成AC自动机即可。
我一开始写了原始的AC自动机,写挂了。后来思考了一下,应当用Trie图,机智地1A。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 const int MAXN=100000+50; 8 char str[MAXN]; 9 int n,cnt; 10 struct ACauto 11 { 12 ACauto* next[26]; 13 ACauto* fail; 14 int id; 15 int sign; 16 ACauto() 17 { 18 for (int i=0;i<26;i++) next[i]=NULL; 19 fail=NULL; 20 id=++cnt; 21 sign=0; 22 } 23 }; 24 25 ACauto* rt=new ACauto(); 26 27 void insert(char* s,ACauto* rt) 28 { 29 ACauto* tmp=rt; 30 for (int i=0;s[i];i++) 31 { 32 int index=s[i]-'a'; 33 if (tmp->next[index]==NULL) 34 tmp->next[index]=new ACauto(); 35 tmp=tmp->next[index]; 36 } 37 tmp->sign=strlen(s); 38 } 39 40 void buildfail(ACauto* rt)//这里我们建立Trie图而不是Trie树的AC自动机 41 { 42 queue<ACauto*> que; 43 que.push(rt); 44 while (!que.empty()) 45 { 46 ACauto* head=que.front();que.pop(); 47 for (int i=0;i<26;i++) 48 { 49 if (head->next[i]==NULL) 50 { 51 if (head==rt) head->next[i]=rt; 52 else head->next[i]=head->fail->next[i]; 53 } 54 else 55 { 56 if (head==rt) head->next[i]->fail=rt; 57 else 58 { 59 head->next[i]->fail=head->fail->next[i]; 60 //if (head->next[i]->fail->sign) head->next[i]->sign=head->next[i]->fail->sign;/*注意!*/ 61 } 62 que.push(head->next[i]); 63 } 64 } 65 } 66 } 67 68 void init() 69 { 70 cnt=0; 71 scanf("%s",str); 72 scanf("%d",&n); 73 for (int i=0;i<n;i++) 74 { 75 char s[MAXN]; 76 scanf("%s",s); 77 insert(s,rt); 78 } 79 buildfail(rt); 80 } 81 82 void solve() 83 { 84 ACauto* a[MAXN]; 85 char stack[MAXN]; 86 int top=0; 87 a[top]=rt; 88 for (int i=0;str[i];i++) 89 { 90 ACauto* j=a[top]; 91 stack[++top]=str[i]; 92 int index=str[i]-'a'; 93 a[top]=j->next[index]; 94 if (a[top]->sign) top-=a[top]->sign; 95 } 96 stack[top+1]='\0'; 97 puts(stack+1); 98 } 99 100 int main() 101 { 102 init(); 103 solve(); 104 return 0; 105 }