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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

【模板】KMP算法、fail树

發布時間:2023/12/3 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【模板】KMP算法、fail树 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

ACM模板


目錄

      • KMP字符串
      • Fail失配樹

KMP字符串

肖然大佬視頻講解

子串: 從原串中選取連續的一段,即為子串(包括空串)
前綴: pre(s,k)pre(s,k)pre(s,k) 為 s k 個字符構成的子串
后綴: suf(s,k)suf(s,k)suf(s,k) 為 s(k…n) 構成的子串
任何子串都是某個后綴的前綴
最長公共前綴 lcp(s,t)lcp(s,t)lcp(s,t) 和最長公共后綴 lcs(s,t)lcs(s,t)lcs(s,t)

周期:0<p<∣s∣0<p<|s|0<p<ss[i]=s[i+p],?i∈{1,2,…,∣s∣?p}s[i]=s[i+p], \forall i\in\{1,2,\dots,|s|-p\}s[i]=s[i+p],?i{1,2,,s?p},滿足以上條件,稱 ppp為 s 的周期
Border:0<r<∣s∣0<r<|s|0<r<spre(s,r)=suf(s,r)pre(s,r)=suf(s,r)pre(s,r)=suf(s,r),滿足以上條件,稱 pre(s,r)pre(s,r)pre(s,r)為 s 的 border

周期與Border的關系:pre(s,k)pre(s,k)pre(s,k)是 s 的 border ?\Leftrightarrow? ∣s∣?k|s|-ks?k 是 s 的周期
Border的傳遞性:
①串 s 是 t 的 border ,串 t 是 r 的 border,那么 s 是 r 的border
②串 s 是 r 的 border,串 t (∣t∣>∣s∣|t|>|s|t>s)也是 r 的 border,則 s 是 t 的border
記 mb(s) 表示 s 的最長 border 則 mb(s),mb(mb(s))…構成 s 的所有 border

給定一個模式串S,以及一個模板串P,所有字符串中只包含大小寫英文字母以及阿拉伯數字。

模板串P在模式串S中多次作為子串出現。

求出模板串P在模式串S中所有出現的位置的起始下標(0開始)。

#include<iostream> using namespace std; const int N=1000010; int n,m; char p[N],s[N]; int ne[N]; int main() {cin>>n>>p+1>>m>>s+1;// 求ne過程看成兩個相同的串匹配for(int i=2,j=0;i<=n;i++){while(j&&p[i]!=p[j+1]) j=ne[j];if(p[i]==p[j+1]) j++;// i結尾能夠匹配 1~j 那么ne[i]=jne[i]=j;}// 當前需要判斷是否匹配 p[j+1]?=s[i]for(int i=1,j=0;i<=m;i++){while(j&&s[i]!=p[j+1]) j=ne[j];if(s[i]==p[j+1]) j++;if(j==n){cout<<i-n<<' ';j=ne[j];}}return 0; }

Fail失配樹

概念以及構造: 將 next[i] 視為 i 點的父節點,那么通過 next 數組可以把 0~N 點連成一棵樹,滿足性質:

  • 點 i 的所有祖先都是前綴 pre(s,i) 的 border
  • 沒有祖先關系的兩個點 i,j 沒有 border 關系

聯系: 計算 next[i] 的過程可以看作:從 j=fa[i-1] 開始不斷往上走,找到第一個滿足 s[j+1]=s[i] 的點,把點 i 的父親設為 j+1

#include<string> #include<iostream> using namespace std; const int N=1000010; int ne[N]; int fa[N][21],dep[N]; string s; int n; int lca(int a,int b) {if(dep[a]<dep[b]) swap(a,b);for(int k=20;k>=0;k--)if(dep[fa[a][k]]>=dep[b]) a=fa[a][k];if(a==b) return a;for(int k=20;k>=0;k--)if(fa[a][k]!=fa[b][k]){a=fa[a][k];b=fa[b][k];}return fa[a][0]; } int main() {cin>>s;n=s.size();s="."+s;dep[0]=1,dep[1]=2;fa[1][0]=0;for(int i=2,j=0;i<=n;i++){while(j&&s[i]!=s[j+1]) j=ne[j];if(s[i]==s[j+1]) j++;ne[i]=j;// 構建失配樹fa[i][0]=j;dep[i]=dep[j]+1;for(int k=1;k<=20;k++)fa[i][k]=fa[fa[i][k-1]][k-1];}int q;cin>>q;while(q--){int a,b;cin>>a>>b;int pab=lca(a,b);// 注意本身是公共祖先的情況if(a==pab||b==pab) cout<<ne[pab]<<'\n';else cout<<pab<<'\n';}return 0; }

總結

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

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