正题

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


题目大意

开始一个空串,\(n\)个操作

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

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

\(1\leq n\leq 10^5\)


解题思路

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

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

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

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

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

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

这样复杂度就到了\(O(n\log n)\)了


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】的更多相关文章

  1. 【KMP】【最小表示法】NCPC 2014 H clock pictures

    题目链接: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1794 题目大意: 两个无刻度的钟面,每个上面有N根针(N<=200000),每个 ...

  2. 【动态规划】【KMP】HDU 5763 Another Meaning

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5763 题目大意: T组数据,给两个字符串s1,s2(len<=100000),s2可以被解读成 ...

  3. HDOJ 2203 亲和串 【KMP】

    HDOJ 2203 亲和串 [KMP] Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...

  4. 【KMP】Censoring

    [KMP]Censoring 题目描述 Farmer John has purchased a subscription to Good Hooveskeeping magazine for his ...

  5. 【KMP】OKR-Periods of Words

    [KMP]OKR-Periods of Words 题目描述 串是有限个小写字符的序列,特别的,一个空序列也可以是一个串.一个串P是串A的前缀,当且仅当存在串B,使得A=PB.如果P≠A并且P不是一个 ...

  6. 【KMP】Radio Transmission

    问题 L: [KMP]Radio Transmission 题目描述 给你一个字符串,它是由某个字符串不断自我连接形成的.但是这个字符串是不确定的,现在只想知道它的最短长度是多少. 输入 第一行给出字 ...

  7. 【kmp】似乎在梦中见过的样子

    参考博客: BZOJ 3620: 似乎在梦中见过的样子 [KMP]似乎在梦中见过的样子 题目描述 「Madoka,不要相信QB!」伴随着Homura的失望地喊叫,Madoka与QB签订了契约. 这是M ...

  8. 【POJ2752】【KMP】Seek the Name, Seek the Fame

    Description The little cat is so famous, that many couples tramp over hill and dale to Byteland, and ...

  9. 【POJ2406】【KMP】Power Strings

    Description Given two strings a and b we define a*b to be their concatenation. For example, if a = & ...

随机推荐

  1. WPF 附件路由事件

    public class Person { public static readonly RoutedEvent NameChangedEvent = EventManager.RegisterRou ...

  2. 【GIS】点图层符号的方向和大小

    方向:根据属性字段设置点图层中每个要素的符号方向和大小, 1 所有要素使用同一种符号---简单渲染 在图层属性---符号系统---单一符号中进行设置,首先设置符号,在后面的[高级]选项按钮中分别设置[ ...

  3. openCV入门系列教学(一) 图像的读取、展示与保存

    序言 笔者最近做了两个CV领域的项目,因为数据量不足所以主要使用的是传统的CV方法.这时候不得不夸一句opencv库,让复杂的算法原理变得如此简单(调包调参侠表示很骄傲).所以闲暇下来对opencv的 ...

  4. Node.js & Kubernetes Graceful Shutdown

    k8s-graceful-shutdown:该库提供了使用 Kubernetes 实现 Graceful Shutdown(优雅退出) Node.js App 的资源. 问题描述 在 kubernet ...

  5. tensorflow models flags 初步使用

    参考官方仓库:https://github.com/tensorflow/models/tree/master/official/utils/flags 测试Demo代码如下: from absl i ...

  6. SQLServer数据库查询语法

    SQLServer数据库查询语法 前言: SQLServer数据库介绍: SQLServer数据库是微软公司推出的一款关系型数据库系统,SQL Server是一个可扩展的.高性能的.为分布式客户机/服 ...

  7. 初识Ansible 01

    自动化运维工具有很多,从实现的功能.维护的成本.使用的系统来选择,几种常用运维工具比较: Puppet基于 Ruby 开发,采用 C/S 架构,扩展性强,基于 SSL,远程命令执行相对较弱 SaltS ...

  8. 🏆【Alibaba工具型技术系列】「EasyExcel技术专题」摒除OOM!让你的Excel操作变得更加优雅和安全

    前提概要 针对于后端开发者而言的,作为报表的导入和导出是一个很基础且有很棘手的问题!之前常用的工具和方案大概有这么几种: JXL(Java Excel API 工具服务),此种只支持xls的文件格式, ...

  9. Golang入门学习(五):异常处理

    文章目录 2.5 错误处理机制 2.5.1 基本说明 2.5.2 入门示例 2.5.3 自定义错误 2.5 错误处理机制 2.5.1 基本说明 Go语言追求简洁优雅,因此并不支持传统的try-catc ...

  10. Identity用户管理入门三(注册用户)

    用户注册主要有2个方法,1.密码加密 2.用户注册 3.ASP.NET Core Identity 使用密码策略.锁定和 cookie 配置等设置的默认值. 可以在类中重写这些设置 Startup(官 ...