AC_Automata模板
生活随笔
收集整理的這篇文章主要介紹了
AC_Automata模板
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
#include<bits/stdc++.h>
using namespace std;
#define ll long longint ans=0;const int maxnode=1e6+7;
const int sigma_size=26;
struct AC_Automata
{ int ch[maxnode][sigma_size]; int val[maxnode]; // 每個字符串的結(jié)尾結(jié)點都有一個非0的val int f[maxnode]; // fail函數(shù) int last[maxnode]; // last[i]=j表j節(jié)點表示的單詞是i節(jié)點單詞的后綴,且j節(jié)點是單詞節(jié)點 int sz; //初始化0號根節(jié)點的相關(guān)信息 void init() { sz=1; memset(ch[0],0,sizeof(ch[0])); val[0]=0; } void insert(char *s,int v) { int u=0; for(int i=0; s[i]; i++) { int id=s[i]-'a'; if(ch[u][id]==0) { ch[u][id]=sz; memset(ch[sz],0,sizeof(ch[sz])); val[sz++]=0; } u=ch[u][id]; } val[u]+=v; } void getFail() { queue<int> q; last[0]=f[0]=0; for(int i=0; i<sigma_size; i++) { int u=ch[0][i]; if(u) { f[u]=last[u]=0; q.push(u); } } while(!q.empty())// 按BFS順序計算fail { int r=q.front(); q.pop(); for(int i=0; i<sigma_size; i++) { int u=ch[r][i]; if(u==0)continue; q.push(u); int v=f[r]; //失配邊嘗試平行傳遞while(v && ch[v][i]==0) v=f[v]; f[u]= ch[v][i]; last[u] = val[f[u]]?f[u]:last[f[u]]; } } } //遞歸打印與結(jié)點i后綴相同的前綴節(jié)點編號 //進入此函數(shù)前需保證val[i]>0 void print(int i) { if(i) { ans+=val[i];val[i]=0; print(last[i]); } } void find(char *s) { int j=0;//j:trie樹中的節(jié)點編號 for(int i=0; s[i]; i++) { int id=s[i]-'a'; while(j && ch[j][id]==0) j=f[j];//ch[j][id]:第j個節(jié)點的id字母子節(jié)點編號 j=ch[j][id]; if(val[j]) print(j); else if(last[j]) print(last[j]); } } };
AC_Automata ac; const int maxn=1e6+7;
char ori[maxn];
char tar[maxn];int main(){int t;scanf("%d",&t);while(t--){ans=0;ac.init();int n;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%s",tar);ac.insert(tar,1);}ac.getFail();scanf("%s",ori);ac.find(ori);printf("%d\n",ans);}
}
自動機的英文念起來好中二啊,
自動機就是trie樹和kmp算法的組合,多模板匹配的首選算法
兩種快樂的算法重疊在一起,就有了自動機(
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
貼一個輕量化的板子,原題HDU3065
#include<bits/stdc++.h> using namespace std; #define ll long long const int maxn=2e6+7; const int maxm=55; const int maxnode=1010*51; const int sigma=128-30;int n,m; int vis[1010]; char word[1010][55]; char ori[maxn];struct automata{int ch[maxnode][sigma];int val[maxnode];int f[maxnode];int sz;int newnode(){memset(ch[sz],0,sizeof(ch[sz]));f[sz]=val[sz]=0;return sz++;}void init(){memset(val,0,sizeof(val));sz=0;newnode();}void insert(char s[],int v){ int u=0;for(int i=0;s[i];i++){int &x=ch[u][s[i]-30];u=x?x:x=newnode(); }val[u]=v;}void build(){queue<int>q;q.push(0); while(!q.empty()){int u=q.front();q.pop();for(int i=0;i<sigma;i++){int v=ch[u][i];if(!v)ch[u][i]=ch[f[u]][i];else q.push(v);if(u&&v)f[v]=ch[f[u]][i];}}}int find(char s[]){int j=0;for(int i=0;s[i];i++){int id=s[i]-30;j=ch[j][id];int tmp=j;while(tmp){vis[val[tmp]]++;tmp=f[tmp];}}} }ac;int main(){while(~scanf("%d",&n)){memset(vis,0,sizeof(vis)); ac.init();for(int i=1;i<=n;i++){scanf("%s",word[i]);ac.insert(word[i],i);}ac.build();scanf("%s",ori);ac.find(ori);for(int i=1;i<=n;i++){if(vis[i])printf("%s: %d\n",word[i],vis[i]);}} }轉(zhuǎn)載于:https://www.cnblogs.com/Drenight/p/8611322.html
總結(jié)
以上是生活随笔為你收集整理的AC_Automata模板的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 201521123007《Java程序设
- 下一篇: hibernate 表关系映射详解之多对