日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

AC_Automata模板

發布時間:2024/1/17 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AC_Automata模板 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
#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]; // 每個字符串的結尾結點都有一個非0的val int f[maxnode]; // fail函數 int last[maxnode]; // last[i]=j表j節點表示的單詞是i節點單詞的后綴,且j節點是單詞節點 int sz; //初始化0號根節點的相關信息 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]]; } } } //遞歸打印與結點i后綴相同的前綴節點編號 //進入此函數前需保證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樹中的節點編號 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個節點的id字母子節點編號 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]);}} }

轉載于:https://www.cnblogs.com/Drenight/p/8611322.html

總結

以上是生活随笔為你收集整理的AC_Automata模板的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。