P5287-[HNOI2019]JOJO【KMP】

1|0正题

题目链接:https://www.luogu.com.cn/problem/P5287


1|1题目大意

开始一个空串,n个操作

  1. 在末尾加入xc字符(保证和c和前面的字符不同)
  2. 返回到第x次操作之后

每次操作完成后求所有前缀的最长的border长度和

1n105


1|2解题思路

二操作好像是一个离线树能搞出来的先只考虑一操作,因为是相当于求kmp之后的next和,所以可以考虑一下用kmp

每个插入操作我们可以看做插入了一个二元组(c,x)nxti表示按照二元组完全匹配来KMP的next数组。

然后求答案的时候设现在这个二元组(c,x),已经匹配到nowc,然后往前跳nxt的时候如果下一个二元组的字符是c且数量x>now那么我们就往后计算答案然后让now=x

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

然后这样跑是能过的,但是加了二操作之后就会T,因为KMP是均摊复杂度的,会被hack

所以考虑一下怎么优化,我们知道broder可以被划分成log个等差数列,而且一定是按照长度来排列的,如果我们发现我们跳进了一个无法匹配的等差数列中我们就直接跳到这个等差数列结束的位置因为这个等差数列中已经不能匹配了。

这样复杂度就到了O(nlogn)


1|3code

#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; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/14912382.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(82)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示