问题引入
考虑KMP问题的升级版,即有多个模式串,单个文本串。问匹配次数。
问题解决
暴力KMP
考虑对于每一个模式串建一个\(fail\)然后对于每一个模式串都和文本串暴力跑。
AC自动机
前置知识
Trie树,bfs……没什么好说的。
算法实现
我们考虑将所有的模式串放到一颗\(Trie\)树,如果匹配失败的话转移到\(fail\)指针上面去,这样子复杂度就是\(O(n)\)的了 。
唯一的问题在于\(fail\)怎么构建,直接$BFS即可。
代码实现
void insert(char *s){ int l=strlen(s),pos=0; for(int i=0;i<l;i++){ int x=s[i]-'a'; if(!ch[pos][x])ch[pos][x]=++tot; pos=ch[pos][x]; } siz[pos]++; } queue<int>Q; void get_fail(){ for(int i=0;i<26;i++) if(ch[0][i]){ Q.push(ch[0][i]);fail[ch[0][i]]=0; } while(!Q.empty()){ int u=Q.front();Q.pop(); for(int i=0;i<26;i++){ int &v=ch[u][i]; if(v){ fail[v]=ch[fail[u]][i];Q.push(v); } else v=ch[fail[u]][i]; } } } int query(char *s){ int l=strlen(s),pos=0,ans=0; for(int i=0;i<l;i++){ int x=s[i]-'a';pos=ch[pos][x]; for(int u=pos;u &&~siz[u];u=fail[u]){ ans+=siz[u];siz[u]=-1; } } return ans; }