AC自动机 重点总结

2019-04-13 21:31发布

算法大致过程及分析

前几天瞎搞了ac自动机模板,本文将ac自动机算法较重要的地方及实现细节记录下来。
AC自动机是著名的多串模式匹配算法。
形式上说,就是一堆模式串,一个文本串,可以将模式串与文本串匹配。
大体实现就是将所有模式串存到一个trie里,匹配就在trie上面走,若失配则走失配指针到一个最优的能继续匹配的结点。
当然,在匹配的时候,会有下面这种情况需要特殊判断

盗个图,哈(此图原出处
模式串有ac,abc,bc
文本串为acabc
那么匹配了abc之后,bc就被忽略了,但事实上也要被匹配到。
那么这些遗漏的串都是abc的后缀,所以要沿着fail链往上找。
这里有一个小优化
我们就可以在求fail链的时候顺带求出一个点fail链上最近一个单词末尾的结点,设为up[v]
那么匹配了v点就沿着up链往上走即可。
并不知道效果怎么样。
L表示模式串总长度,N表示文本串总长度
时间复杂度是O(L+N)
本蒟蒻并不会证明,感性理解吧
因为不可能每一次都能沿fail链跳很多步,跳着跳着就跳到根了,要再有跳很多步的机会又要匹配很多字符
上面一行纯属扯淡

代码实现及注意事项

  • 个人习惯把1设为trie的根
  • trie的存储依题而定,或许可以26个指针,有时卡空间的话要用模拟链表
  • 如果多组数据要记得清空tot,trie[][],标记数组,最好不要memset
  • 建fail参见下面代码
void bfs() { q.push(1); while(!q.empty()) { int v=q.front();q.pop(); fo(i,0,25) if(trie[v][i]) { int x=trie[v][i],y=fail[v]; while(y && !trie[y][i]) y=fail[y]; if(y) fail[x]=trie[y][i]; else fail[x]=1; q.push(x); } } } 匹配是这个样子的 int x=1; fo(i,1,len) { int y=s[i]-'a'; while(x!=1 && !trie[x][y]) x=fail[x]; if(trie[x][y]) x=trie[x][y]; for(int v=x;v!=1;v=fail[v]) { //这里视题目而定 } }