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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

AC自动机:例题与机制详解

發布時間:2023/12/3 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AC自动机:例题与机制详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

介紹

AC自動機是kmp算法和trie樹的結合
大體就是做這樣的題用:

可以發現,這題和trie樹的區別是把多個單詞往一篇文章匹配,而trie恰好相反
匹配的時候其實就是判斷子串,所以又用到了kmp
定義失配指針nxt[i]:表示root到nxt[i]結點的字符串是到 i 結點的字符串的在本樹中的最長后綴(其實和kmp差不多啦)
設文章下一個字是s,當前trie樹結點是a
每次發現a結點下方沒有s的兒子(膝下無子 ) 就回去重新找失配指針
現在考慮處理失配指針
因為顯然nxt[i]的深度小于i,所以采用bfs,從而保證當前結點以上的所有的結點的nxt都解決完

核心代碼

void solve(){for(int i=1;i<=26;i++) tree[0][i]=1;int q[N]={};q[1]=1;nxt[1]=0;for(int st=1,ed=1;st<=ed;st++){int now=q[st];for(int i=1;i<=26;i++){if(!tree[now][i]) tree[now][i]=tree[nxt[now]][i];else{q[++ed]=tree[now][i];int v=nxt[now];nxt[tree[now][i]]=tree[v][i];}}} }

看代碼也可以發現,當tree[i][j]無定義時,直接指向了它的失配指針
然后就好辦了

void ac(){int p=1;int l=strlen(s+1);for(int i=1;i<=l;i++) a[i]=s[i]-'a'+1;for(int i=1;i<=l;i++){p=tree[p][a[i]];int k=p;while(k>1){//防止遺漏ans+=end[k];end[k]=0;//本題需要清零k=nxt[k];}}return; }

例題代碼

#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<map> #include<vector> #include<queue> #include<stack> #include<deque> #include<set> #include<string> #include<iostream> #include<climits> #define mem(a,b) memset(a,b,sizeof(a)); using namespace std; const int M=1000050; const int N=100050; const int mod=100003; typedef pair<int,int>pr; int m,n,k,b,c,d; int num=1,tree[N][28],end[M]; char s[M]; int a[M]; void add(){int l1=strlen(s+1);for(int i=1;i<=l1;i++) a[i]=s[i]-'a'+1;int u=1;for(int i=1;i<=l1;i++){if(!tree[u][a[i]]) tree[u][a[i]]=++num;u=tree[u][a[i]];}end[u]++; } int nxt[N]; void solve(){for(int i=1;i<=26;i++) tree[0][i]=1;int q[N]={};q[1]=1;nxt[1]=0;for(int st=1,ed=1;st<=ed;st++){int now=q[st];for(int i=1;i<=26;i++){if(!tree[now][i]) tree[now][i]=tree[nxt[now]][i];else{q[++ed]=tree[now][i];int v=nxt[now];nxt[tree[now][i]]=tree[v][i];}}} } int ans=0; void ac(){int p=1;int l=strlen(s+1);for(int i=1;i<=l;i++) a[i]=s[i]-'a'+1;for(int i=1;i<=l;i++){p=tree[p][a[i]];int k=p;while(k>1){ans+=end[k];end[k]=0;k=nxt[k];}}return; } int main(){scanf("%d",&k);while(k--){mem(tree,0);mem(end,0);ans=0;num=1;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%s",s+1);add();}scanf("%s",s+1);solve();ac();printf("%d\n",ans);} } /* 1 5 she he say shr her yasherhs */

thanks for reading!

總結

以上是生活随笔為你收集整理的AC自动机:例题与机制详解的全部內容,希望文章能夠幫你解決所遇到的問題。

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