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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

P5287-[HNOI2019]JOJO【KMP】

發布時間:2023/12/3 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P5287-[HNOI2019]JOJO【KMP】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題

題目鏈接:https://www.luogu.com.cn/problem/P5287


題目大意

開始一個空串,nnn個操作

  • 在末尾加入xxxccc字符(保證和ccc和前面的字符不同)
  • 返回到第xxx次操作之后
  • 每次操作完成后求所有前綴的最長的borderborderborder長度和

    1≤n≤1051\leq n\leq 10^51n105


    解題思路

    二操作好像是一個離線樹能搞出來的先只考慮一操作,因為是相當于求kmpkmpkmp之后的nextnextnext和,所以可以考慮一下用kmpkmpkmp

    每個插入操作我們可以看做插入了一個二元組(c,x)(c,x)(c,x)nxtinxt_inxti?表示按照二元組完全匹配來KMP的nextnextnext數組。

    然后求答案的時候設現在這個二元組(c,x)(c,x)(c,x),已經匹配到nownownowccc,然后往前跳nxtnxtnxt的時候如果下一個二元組的字符是ccc且數量x>nowx>nowx>now那么我們就往后計算答案然后讓now=xnow=xnow=x

    然后最后剩下的一些如果能和第一個匹配就全都匹配。

    然后這樣跑是能過的,但是加了二操作之后就會TTT,因為KMP是均攤復雜度的,會被hackhackhack

    所以考慮一下怎么優化,我們知道broderbroderbroder可以被劃分成logloglog個等差數列,而且一定是按照長度來排列的,如果我們發現我們跳進了一個無法匹配的等差數列中我們就直接跳到這個等差數列結束的位置因為這個等差數列中已經不能匹配了。

    這樣復雜度就到了O(nlog?n)O(n\log n)O(nlogn)


    code

    #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #define ll long long using namespace std; const ll N=1e5+10,P=998244353; ll n,len,ch[N][2],s[N][3],ans[N],nxt[N],prt[N],p[N]; vector<ll> e[N]; ll gs(ll l,ll r) {return (r+l)*(r-l+1)/2;} void dfs(ll x){ll i=nxt[len++];s[len][0]=ch[x][0];s[len][1]=ch[x][1];s[len][2]=s[len-1][2]+ch[x][1];ans[len]=ans[len-1];nxt[len]=0;if(len==1){ans[len]=gs(1,ch[x][1]-1);}else{ll d=len-i;while(i&&(s[i+1][0]!=ch[x][0]||s[i+1][1]!=ch[x][1])){if(i-nxt[i]==d)i=i%d+d;d=i-nxt[i];i=nxt[i];}nxt[len]=i+(i||(ch[x][0]==s[1][0]&&ch[x][1]>=s[1][1]));ll now=0;i=nxt[len-1],d=len-1-i;while(now<ch[x][1]&&i){if(s[i+1][0]==ch[x][0]&&s[i+1][1]>now){ans[len]+=gs(s[i][2]+now+1,s[i][2]+min(ch[x][1],s[i+1][1]));now=s[i+1][1];}if(i-nxt[i]==d)i=i%d+d;d=i-nxt[i];i=nxt[i];}if(now<ch[x][1]&&s[1][0]==ch[x][0]){if(s[i+1][1]>now)ans[len]+=gs(now+1,min(ch[x][1],s[i+1][1]));now=max(now,min(ch[x][1],s[i+1][1]));ans[len]+=s[1][1]*(ch[x][1]-now);}}prt[x]=ans[len];for(ll i=0;i<e[x].size();i++)dfs(e[x][i]);len--;return; } signed main() {scanf("%lld",&n);for(ll i=1;i<=n;i++){ll op;scanf("%lld ",&op);if(op==1){scanf("%lld %c",&ch[i][1],&ch[i][0]);e[p[i-1]].push_back(p[i]=i);}else{ll x;scanf("%lld",&x);p[i]=p[x];}}for(ll i=0;i<e[0].size();i++)dfs(e[0][i]);for(ll i=1;i<=n;i++)printf("%lld\n",prt[p[i]]%P);return 0; }

    總結

    以上是生活随笔為你收集整理的P5287-[HNOI2019]JOJO【KMP】的全部內容,希望文章能夠幫你解決所遇到的問題。

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