洛谷P5357 - 【模板】AC自动机(二次加强版)(AC自动机+fail树)
生活随笔
收集整理的這篇文章主要介紹了
洛谷P5357 - 【模板】AC自动机(二次加强版)(AC自动机+fail树)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
題目鏈接:點(diǎn)擊查看
題目大意:給出n個(gè)模式串,問在主串中分別出現(xiàn)了多少次
題目分析:如果像以往那樣,在匹配的時(shí)候fail指針亂跳的話,那么是錯(cuò)誤的AC自動(dòng)機(jī)使用方法,時(shí)間復(fù)雜度也大大上升,接近于暴力的復(fù)雜度,正確的做法是建立一棵fail樹,原理就是因?yàn)槊恳粋€(gè)節(jié)點(diǎn)的fail指針都是唯一的,并且是指向另外的一個(gè)節(jié)點(diǎn),也就是說一個(gè)節(jié)點(diǎn)可以被多個(gè)fail指針?biāo)?#xff0c;那么我們可以將這條邊的方向反過來,也就是一個(gè)節(jié)點(diǎn)可以到達(dá)多個(gè)fail指針?biāo)傅钠渌?jié)點(diǎn),這樣就形成了一棵fail樹,接下來我們就可以在自動(dòng)機(jī)上記錄每個(gè)模式串在字典樹的終止節(jié)點(diǎn)上匹配了多少次,最后跑一次簡(jiǎn)單樹形dp就跑出每個(gè)點(diǎn)的答案了
在建立字典樹的時(shí)候記得將每個(gè)字符串的編號(hào)和終止節(jié)點(diǎn)映射一下,方便答案的輸出
代碼:
#include<iostream> #include<cstdlib> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<climits> #include<cmath> #include<cctype> #include<stack> #include<queue> #include<list> #include<vector> #include<set> #include<map> #include<sstream> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=2e6+100;char s[N];int trie[N][26],cnt;int rk[N];//rk[序號(hào)]=編號(hào):序號(hào)與終止節(jié)點(diǎn)的映射int fail[N];int dp[N];vector<int>node[N];void insert_word(int x) {int pos=0;for(int i=0;s[i];i++){int to=s[i]-'a';if(!trie[pos][to])trie[pos][to]=++cnt;pos=trie[pos][to];}rk[x]=pos; }void getfail() {queue<int>q;for(int i=0;i<26;i++){int p=trie[0][i];if(p){fail[p]=0;q.push(p);}}while(!q.empty()){int cur=q.front();q.pop();for(int i=0;i<26;i++){int p=trie[cur][i];if(p){fail[p]=trie[fail[cur]][i];q.push(p);}elsetrie[cur][i]=trie[fail[cur]][i];}} }void search_word() {int pos=0;for(int i=0;s[i];i++){int to=s[i]-'a';pos=trie[pos][to];dp[pos]++;//記錄終止節(jié)點(diǎn)在主串的出現(xiàn)次數(shù)} }void dfs(int u) {for(auto v:node[u]){dfs(v);dp[u]+=dp[v];} }int main() { // freopen("input.txt","r",stdin); // ios::sync_with_stdio(false);int n;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%s",s);insert_word(i);}getfail();for(int i=1;i<=cnt;i++)//建立fail樹node[fail[i]].push_back(i);scanf("%s",s);search_word();dfs(0);for(int i=1;i<=n;i++)printf("%d\n",dp[rk[i]]);return 0; }?
總結(jié)
以上是生活随笔為你收集整理的洛谷P5357 - 【模板】AC自动机(二次加强版)(AC自动机+fail树)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDU - 3966 Aragorn's
- 下一篇: HDU - 1150 Machine S