目的:已知n个长度不同的模式串,以及一个长度为m的串S,求在S中出现过多少个模式串。
步骤:
①建立trie树
②建立失败指针
③字符串匹配
fail[now]:当前节点now的失败指针指向的地方
trie[now][i]:下一个字母为i+'a'的节点的下标为trie[now][i]
build过程:如果有这个子节点为i+'a',则让这个节点的失败指针指向他父亲节点的失败指针所指向的那个节点的下一个节点,否则就让当前节点的这个子节点指向当前节点fail指针的这个节点。
https://blog.csdn.net/bestsort/article/details/82947639
自用模板:

#include <bits/stdc++.h> using namespace std; const int MAX_N=10000; const int MAX_C=26; struct AC_Automaton { int ch[MAX_N][MAX_C],fail[MAX_N],cnt[MAX_N]; int tot; void init() { memset(ch,-1,sizeof(ch)); memset(fail,0,sizeof(fail)); tot=0; memset(cnt,0,sizeof(cnt)); } void insert(char* str) { int p=0; for(int i=0;str[i];i++) { if(ch[p][str[i]-'a']==-1) { ch[p][str[i]-'a']=++tot; } p=ch[p][str[i]-'a']; } cnt[p]++; } void build() { int l=0,r=0,Q[MAX_N]; for(int i=0;i<MAX_C;i++) { if(ch[0][i]==-1) { ch[0][i]=0; } else { Q[r++]=ch[0][i]; } } while(l<r) { int p=Q[l++]; for(int i=0;i<MAX_C;i++) { if(ch[p][i]==-1) { ch[p][i]=ch[fail[p]][i]; } else { fail[ch[p][i]]=ch[fail[p]][i]; Q[r++]=ch[p][i]; } } } } int count(char* str) { int ret=0,p=0; for(int i=0;str[i];i++) { p=ch[p][str[i]-'a']; int tmp=p; while(tmp) { ret+=cnt[tmp]; cnt[tmp]=0; tmp=fail[tmp]; } } return ret; } }ac; int main() { ac.init(); ac.insert("abcd"); ac.insert("bcd"); ac.insert("cd"); ac.insert("d"); ac.build(); cout<<ac.count("abcd")<<endl; return 0; }
s中出现过的模式串都删除,删掉后可首尾连接重新包含模式串,模式串不会是另一个模式串的子串。请输出删除后的s

#include<bits/stdc++.h> using namespace std; const int maxn=1e5+10; const int maxc=26; struct ac_automaton { int ch[maxn][maxc],fail[maxn],cnt[maxn],stk[maxn]; int tot,top; void init() { memset(ch,-1,sizeof(ch)); memset(fail,0,sizeof(fail)); tot=top=0; memset(cnt,0,sizeof(cnt)); memset(stk,0,sizeof(stk)); } void insert(char* str) { int p=0; for(int i=0;str[i];i++) { if(ch[p][str[i]-'a']==-1)ch[p][str[i]-'a']=++tot; p=ch[p][str[i]-'a']; } cnt[p]=strlen(str); } void build() { int l=0,r=0,Q[maxn]; for(int i=0;i<maxc;i++) { if(ch[0][i]==-1)ch[0][i]=0; else Q[r++]=ch[0][i]; } while(l<r) { int p=Q[l++]; for(int i=0;i<maxc;i++) { if(ch[p][i]==-1)ch[p][i]=ch[fail[p]][i]; else fail[ch[p][i]]=ch[fail[p]][i],Q[r++]=ch[p][i]; } } } void count(char* str) { int p=0,a=0; for(int i=0;str[i];i++) { p=ch[p][str[i]-'a']; str[a++]=str[i]; stk[top++]=p; if(cnt[p]) { a-=cnt[p]; top-=cnt[p]; p=top?stk[top-1]:0; } } str[a]='