[模板][P3808]AC自動機(簡單版)
阿新 • • 發佈:2019-02-15
sin class ac自動機 bit spa trie space pac strlen
模板,詳見代碼:
#include<bits/stdc++.h> using namespace std; const int mxn=1e7+5; char str[mxn],p[80]; queue<int > q; namespace Trie { int tot,fail[mxn],val[mxn]; int t[mxn][26]; void ins(char *s) { int len=strlen(s),u=0; for(int i=0;i<len;++i) { if(!t[u][s[i]-'a']) t[u][s[i]-'a']=++tot; u=t[u][s[i]-'a']; } ++val[u]; }; void build() { for(int i=0;i<26;++i) if(t[0][i]) fail[t[0][i]]=0,q.push(t[0][i]); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=0;i<26;++i) { if(t[u][i]) fail[t[u][i]]=t[fail[u]][i],q.push(t[u][i]); else t[u][i]=t[fail[u]][i]; //類似於路徑壓縮的優化 } } }; int query(char *s) { int len=strlen(s),u=0,ans=0; for(int i=0;i<len;++i) { u=t[u][s[i]-'a']; //每次從大到小統計文本串以第i個字符結束的所有串 for(int v=u;val[v]!=-1;v=fail[v]) ans+=val[v],val[v]=-1; //剪枝,跳過無需再跳 } return ans; }; } using namespace Trie; int main() { int n; scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%s",p),ins(p); build(); scanf("%s",str); printf("%d",query(str)); return 0; }
[模板][P3808]AC自動機(簡單版)