AC自动机
Posted popo-black-cat
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AC自动机相关的知识,希望对你有一定的参考价值。
AC自动机模版:
就注意一个地方,就是对于母串的一部分,可能存在不止一个子串与之匹配,也就是说对于所有的nxt,都要走一遍看看能不能碰到end。
由于一个子串出现一次就不能再出现了(问多少个子串出现过不是嘛),那么找到一个 end ,就把这个end变成 -1 ,找到end是 -1 的就不用继续往下找,因为这个 end 以及这个 end 之后的 nxt 都没算过一次了。
剩下的,就像那一句老话:模拟即可。
#include<cstdio> #include<iostream> #include<queue> #include<cstring> #include<algorithm> #include<cmath> using namespace std; #define maxn 1000000 struct Tree { int vis[26]; int nxt,end; } AC[maxn]; int cnt; void build(string s) { int len=s.length(); int now=0; for(int i=0;i<len;i++) { if(!AC[now].vis[s[i]-‘a‘]) AC[now].vis[s[i]-‘a‘]=++cnt; now=AC[now].vis[s[i]-‘a‘]; } AC[now].end++; } void Get_nxt() { queue<int> Q; for(int i=0;i<26;i++) if(AC[0].vis[i]) Q.push(AC[0].vis[i]); while(!Q.empty()) { int u=Q.front(); Q.pop(); for(int i=0;i<26;i++) { int son=AC[u].vis[i]; if(son) { AC[son].nxt=AC[AC[u].nxt].vis[i]; Q.push(son); } else AC[u].vis[i]=AC[AC[u].nxt].vis[i]; } } } int query(string s) { int len=s.length(); int now=0,ans=0; for(int i=0;i<len;i++) { now=AC[now].vis[s[i]-‘a‘]; for(int t=now;t&&AC[t].end!=-1;t=AC[t].nxt) { ans+=AC[t].end; AC[t].end=-1; } } return ans; } int main() { int n; string s; scanf("%d",&n); for(int i=1;i<=n;i++) { cin>>s; build(s); } Get_nxt(); cin>>s; printf("%d\n",query(s)); return 0; }
以上是关于AC自动机的主要内容,如果未能解决你的问题,请参考以下文章
HDU4057 Rescue the Rabbit(AC自动机+状压DP)
Codeforces 86C Genetic engineering(AC自动机+DP)
POJ1699 Best Sequence(AC自动机+状压DP)