A. Censoring
题目描述
输入格式
输出格式
样例
AC自动机+栈,和之前kmp一样,不过这个是多模式串用到AC自动机。
trie图中记录单词结尾和单词长度,维护一个栈,依次将字符入栈匹配,若匹配到一个单词的结尾,top-=len单词出栈,用一个数组记录top=i时指针的状态,在弹栈之后将指针恢复即可。
然而标准的AC自动机会TLE(从此对AC自动机无爱了),所以我又写了一个trie图。
考试时有人用Hash AC了…(根据第三题的教训),我觉得也应该去学一下……
#include<iostream> #include<cstdio> #include<cstring> #include<time.h> using namespace std; struct trie { int count; trie *nxt[26],*fail; trie() { count=0; fail=NULL; for(int i=0;i<26;i++)nxt[i]=NULL; } }*q[2000000],*root=new trie(); int head,tail; char str[100010]; char key[100010]; int n; char stack[100010]; trie *ff[100010]; int top; void insert(char s[],trie *root) { int len=strlen(s); trie *p=root; int i=0,index; while(s[i]) { index=s[i]-'a'; if(p->nxt[index]==NULL)p->nxt[index]=new trie(); p=p->nxt[index]; i++; } p->count=len; } void build_ac(trie *root) { q[++tail]=root; while(head!=tail) { trie *now=q[++head]; for(int i=0;i<26;++i) { if(now->nxt[i]) { if(now==root) now->nxt[i]->fail=now; else now->nxt[i]->fail=now->fail->nxt[i]; q[++tail]=now->nxt[i]; } else { if(now==root) now->nxt[i]=now; else now->nxt[i]=now->fail->nxt[i]; } } } } inline int read() { int s=0;char a=getchar(); while(a<'0'||a>'9')a=getchar(); while(a>='0'&&a<='9'){s=s*10+a-'0';a=getchar();} return s; } int main() { // freopen("in.txt","r",stdin); // freopen("data14.in","r",stdin); // freopen("cen.out","w",stdout); scanf("%s",str); int len=strlen(str); n=read(); for(int i=1;i<=n;i++) { scanf("%s",key); insert(key,root); } build_ac(root); int index; trie *p=root; trie *temp=NULL; for(int i=0;i<len;i++) { stack[++top]=str[i]; index=str[i]-'a'; ff[top]=p; p=p->nxt[index]; if(p==NULL)p=root; if(p->count) { top-=p->count; p=ff[top+1]; } } for(int i=1;i<=top;i++) putchar(stack[i]); return 0; }