构建字典图实现自动跳转,构建失配指针实现多模式匹配
\(fail\)指针表示文本串在当前节点失配后,我们应该到哪个节点去继续匹配,\(u\)的\(fail\)指针指向\(v\)表示从根到\(v\)的字符串为从根到\(u\)的字符串的最长后缀,用\(bfs\)来构建\(fail\)指针
\(fail[trie[x][i]]=trie[fail[x]][i]\)
相当于在\(x\)和\(fail[x]\)后面加一个字符\(i\),就构成\(fail[trie[x][i]]\)
若发现\(trie[x][i]\)不存在,则直接将其\(trie[fail[x]][i]\)赋值给它,来实现一个类似于路径压缩的操作
\(code\):
void insert(char *str) { int len=strlen(str),cur=0; for(int i=0;i<len;++i) { int ch=str[i]-'a'; if(!trie[cur][ch]) trie[cur][ch]=++tot; cur=trie[cur][ch]; } num[cur]++; } void build() { queue<int> q; for(int i=0;i<26;++i) if(trie[0][i]) q.push(trie[0][i]); while(!q.empty()) { int x=q.front(); q.pop(); for(int i=0;i<26;++i) { int y=trie[x][i]; if(y) { fail[y]=trie[fail[x]][i]; q.push(y); } else trie[x][i]=trie[fail[x]][i]; } } } int query(char *str) { int len=strlen(str),cur=0,ans=0; for(int i=0;i<len;++i) { int ch=str[i]-'a'; cur=trie[cur][ch]; for(int j=cur;num[j]!=-1&&j;j=fail[j]) ans+=num[j],num[j]=-1; } return ans; }
来源:https://www.cnblogs.com/lhm-/p/12229506.html