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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

失配树

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

名字看起來挺高級的,然而其實就是 \(\text{KMP}\) 上樹啦。

我們將每個點的 \(nex[i]\)\(i\) 連邊,那么最終 \(border\) 關系會形成一棵樹,之后就可以在樹上搞事情啦!

P5829 【模板】失配樹

這題比較裸,直接根據定義建樹之后對于兩個前綴求出在 \(fail\) 樹上的最近公共祖先即可。

$\texttt{code}$ // Author:A weak man named EricQian #include<bits/stdc++.h> using namespace std; #define infll 0x7f7f7f7f7f7f7f7f #define inf 0x3f3f3f3f #define Maxn 1000005 #define Maxpown 22 typedef long long ll; inline int rd() {int x=0;char ch,t=0;while(!isdigit(ch = getchar())) t|=ch=='-';while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();return x=t?-x:x; } int n,q,tot; int pre[Maxn],dep[Maxn]; int fa[Maxn][Maxpown]; char s[Maxn]; inline int query(int x,int y) {if(dep[x]>dep[y]) swap(x,y);for(int i=20;i>=0;i--) if(dep[fa[y][i]]>=dep[x]) y=fa[y][i];if(x==y) return fa[x][0];for(int i=20;i>=0;i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];return fa[x][0]; } int main() {//ios::sync_with_stdio(false); cin.tie(0);//freopen(".in","r",stdin);//freopen(".out","w",stdout);scanf("%s",s+1),n=strlen(s+1);for(int i=2,j=0;i<=n;i++){while(j && s[i]!=s[j+1]) j=pre[j];if(s[i]==s[j+1]) j++;pre[i]=j,fa[i][0]=j,dep[i]=dep[j]+1;}for(int i=1;i<=20;i++)for(int j=1;j<=n;j++)fa[j][i]=fa[fa[j][i-1]][i-1];q=rd();for(int i=1,x,y;i<=q;i++) x=rd(),y=rd(),printf("%d\n",query(x,y));//fclose(stdin);//fclose(stdout);return 0; }

小插曲:(小聲)

ZCETHAN 告訴 EricQian 這一題用失配樹做,EricQian 立刻表示它不會失配樹?!具^了 5 秒】EricQian 大聲喊道:我發明了失配樹!

CF432D Prefixes and Suffixes

題意:給你一個長度為 \(n\) 的長字符串,“完美子串”既是它的前綴也是它的后綴,求“完美子串”的個數且統計這些子串的在長字符串中出現的次數。

我們發現對于一個前綴的出現個數其實就是:(難以表述直接用偽代碼列出了)

len=這個前綴的長度 for(int i=1;i<=n;i++)for(int j=i;j;j=nex[j])ans+=(j==len)?1:0;

之后我們發現對于同一個前綴它可能被訪問多次,這個可以直接倒換循環順序實現 \(O(n)\) 解決。(于是你就發明的失配樹)

$\texttt{code}$ // Author:A weak man named EricQian #include<bits/stdc++.h> using namespace std; #define infll 0x7f7f7f7f7f7f7f7f #define inf 0x3f3f3f3f #define Maxn 100005 typedef long long ll; inline int rd() {int x=0;char ch,t=0;while(!isdigit(ch = getchar())) t|=ch=='-';while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();return x=t?-x:x; } inline ll maxll(ll x,ll y){ return x>y?x:y; } inline ll minll(ll x,ll y){ return x<y?x:y; } inline ll absll(ll x){ return x>0ll?x:-x; } inline ll gcd(ll x,ll y){ return (y==0)?x:gcd(y,x%y); } int n,tot; int nex[Maxn],cnt[Maxn]; int ans[Maxn][2]; char s[Maxn]; int main() {//ios::sync_with_stdio(false); cin.tie(0);//freopen(".in","r",stdin);//freopen(".out","w",stdout);scanf("%s",s+1),n=strlen(s+1);for(int i=2,j=0;i<=n;i++){while(j && s[i]!=s[j+1]) j=nex[j];if(s[i]==s[j+1]) j++;nex[i]=j;}for(int i=n;i>=1;i--) cnt[i]++,cnt[nex[i]]+=cnt[i]; // for(int i=1;i<=n;i++) // for(int j=i;j;j=nex[j]) cnt[j]++;ans[++tot][0]=n,ans[tot][1]=1;for(int i=nex[n];i;i=nex[i])ans[++tot][0]=i,ans[tot][1]=cnt[i];printf("%d\n",tot);for(int i=tot;i>=1;i--) printf("%d %d\n",ans[i][0],ans[i][1]);//fclose(stdin);//fclose(stdout);return 0; }

P2375 [NOI2014] 動物園

這道題可以根本不用往失配樹去理解,我們發現每一次最長合法 \(\text{border}\) 的長度最多只會增加 \(1\),那么直接暴力跑 \(\text{KMP}\) 并及時處理 \(\text{border}\) 長度大于一半的情況即可。

一些正確性證明:如果這個位置的 \(\text{border}\) 長度大于了 \(\frac{i}{2}\),這個 \(\text{border}\) 的后綴起始點將永遠不再會成為答案,因此跳出這個 \(\text{border}\) 一定是對的。

$\texttt{code}$ // Author:A weak man named EricQian #include<bits/stdc++.h> using namespace std; #define infll 0x7f7f7f7f7f7f7f7f #define inf 0x3f3f3f3f #define Maxn 1000005 #define mod 1000000007 typedef long long ll; inline int rd() {int x=0;char ch,t=0;while(!isdigit(ch = getchar())) t|=ch=='-';while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();return x=t?-x:x; } inline ll maxll(ll x,ll y){ return x>y?x:y; } inline ll minll(ll x,ll y){ return x<y?x:y; } inline ll absll(ll x){ return x>0ll?x:-x; } inline ll gcd(ll x,ll y){ return (y==0)?x:gcd(y,x%y); } int n,ans; char s[Maxn]; int nex[Maxn],dep[Maxn]; int main() {//ios::sync_with_stdio(false); cin.tie(0);//freopen(".in","r",stdin);//freopen(".out","w",stdout);int T=rd();while(T--){scanf("%s",s+1),n=strlen(s+1),ans=1;dep[1]=1;for(int i=2,j=0;i<=n;i++){while(j && s[i]!=s[j+1]) j=nex[j];if(s[i]==s[j+1]) j++;nex[i]=j,dep[i]=dep[j]+1;}for(int i=2,j=0;i<=n;i++){while(j && s[i]!=s[j+1]) j=nex[j];if(s[i]==s[j+1]) j++;while(j*2>i) j=nex[j];ans=1ll*ans*(1ll*dep[j]+1ll)%mod;}printf("%d\n",ans);}//fclose(stdin);//fclose(stdout);return 0; }

P3426 [POI2005]SZA-Template

考慮設 \(dp(i)\) 表示主串的前綴 \([1,i]\) 需要的最短長度。

容易發現在失配樹上 \(dp(i)\) 沿著樹成單調遞增關系,考慮 \(dp(i)\)\(dp(nex_i)\) 的關系。

如果 \(dp(i)\in (dp(nex_i),nex_i]\),由于 \([1,i]\) 的一個 border 為 \(dp(nex_i)\),所以 \(dp(nex_i)\) 也一定能夠生成這個串。

所以 \(dp(i)\) 能夠生成的串一定是 \(dp(nex_i)\) 能夠生成的真子集,即答案取 \(dp(nex_i)\) 一定比 \((dp(nex_i),nex_i]\) 優。

因此我們只用判斷能否由 \(dp(nex_i)\) 生成 \([1,i]\) 即可,具體即記錄 \(dp(nex_i)\) 能夠生成的最長串 \(s\),如果 \(|s|+|dp(nex_i)|\ge i\) 即可。

如果上述情況不成立,意味著 \(dp(i)=i\)。

$\texttt{code}$ // Author:A weak man named EricQian #include<bits/stdc++.h> using namespace std; #define infll 0x7f7f7f7f7f7f7f7f #define inf 0x3f3f3f3f #define Maxn 500005 typedef long long ll; inline int rd() {int x=0;char ch,t=0;while(!isdigit(ch = getchar())) t|=ch=='-';while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();return x=t?-x:x; } inline ll maxll(ll x,ll y){ return x>y?x:y; } inline ll minll(ll x,ll y){ return x<y?x:y; } inline ll absll(ll x){ return x>0ll?x:-x; } inline ll gcd(ll x,ll y){ return (y==0)?x:gcd(y,x%y); } int n; int nex[Maxn],maxx[Maxn],dp[Maxn]; char s[Maxn]; int main() {//ios::sync_with_stdio(false); cin.tie(0);//freopen(".in","r",stdin);//freopen(".out","w",stdout);scanf("%s",s+1),n=strlen(s+1);for(int i=2,j=0;i<=n;i++){while(j && s[i]!=s[j+1]) j=nex[j];if(s[i]==s[j+1]) j++;nex[i]=j;}for(int i=1;i<=n;i++){if(maxx[dp[nex[i]]]+dp[nex[i]]>=i) dp[i]=dp[nex[i]];else dp[i]=i;maxx[dp[i]]=i;}printf("%d\n",dp[n]);//fclose(stdin);//fclose(stdout);return 0; }

總結

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

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

主站蜘蛛池模板: 伊人导航 | av片国产 | 欧美黑人一区二区 | 免费看黄色片视频 | 福利在线小视频 | 久久成年视频 | 国产高潮呻吟久久 | 日本伦理一区二区三区 | 女人特黄大aaaaaa大片 | 91av福利视频 | 亚洲一 | 原创露脸88av | xxxxhdvideos| av中文在线资源 | 中文字幕第18页 | 福利二区 | 成人精品视频一区二区三区尤物 | 吸咬奶头狂揉60分钟视频 | 黄色免费大片 | 完全免费在线视频 | 亚洲一区a | 黄毛片在线观看 | 中文字幕亚洲色图 | 熟女毛毛多熟妇人妻aⅴ在线毛片 | 国产又粗又硬 | 麻豆视频免费在线观看 | 国产精品五月天 | 99视频精品| 99久久精品一区二区 | 99久久久成人国产精品 | 国产精品一区二区三区四区在线观看 | 色欲久久久天天天综合网精品 | 久久男人 | 少妇又紧又爽视频 | 亚洲熟女乱色一区二区三区久久久 | 亚洲人在线播放 | 一区二区三区黄 | 超碰婷婷 | 国产成人99久久亚洲综合精品 | 亚洲av无码乱码国产精品久久 | 丁香花高清在线观看完整动漫 | 国产精品国产三级国产传播 | 91黄免费| 好色成人网 | 人人草人人澡 | 一级的大片 | 亚洲精品无码久久久 | www精品国产 | 午夜视频在线观看一区二区 | av大全在线播放 | 欧美日韩精品在线播放 | 青青草欧美 | youjizz视频| 日本五十路在线 | 黄色性情网站 | 波多野结衣电车痴汉 | 草久免费视频 | 国产精品一区二区人妻喷水 | 日本天堂网在线观看 | 毛片网站在线免费观看 | 一本色道久久综合狠狠躁 | 99精品欧美一区二区蜜桃免费 | 99视频一区二区 | 午夜插插 | 中文字幕亚洲精品在线 | 不卡av电影在线 | 97人妻精品一区二区三区免费 | 国产精品1区2区3区 在线看黄的网站 | 国产一区二区波多野结衣 | 亚洲三级小说 | 精品国产乱码久久久久久88av | 亚洲爆乳无码精品aaa片蜜桃 | 亚洲毛片在线播放 | 青青草娱乐在线 | 亚洲欧美日韩中文在线 | 久久久久18 | 欧美综合国产 | 欧美综合专区 | 国内自拍青青草 | 亚洲综合色在线 | 久久精品一区二区三区黑人印度 | 91精品人妻互换一区二区 | 国产一级黄色大片 | 欧美日韩国产成人 | 日本东京热一区二区三区 | 久久久久看片 | 黄色小视频免费在线观看 | 日本在线一区二区三区 | 天天超碰| 成人网视频 | 亚洲无吗av| 麻豆黄色片| 永久免费无码av网站在线观看 | 草比网站| 女同性做爰全过程 | 小泽玛利亚在线 | 久久人人爽人人爽人人片亚洲 | 欧美三级不卡 | 成人午夜视频免费看 |