首页 > 其他分享 >P4770 [NOI2018] 你的名字 做题记录

P4770 [NOI2018] 你的名字 做题记录

时间:2023-12-01 20:46:49浏览次数:33  
标签:子串 boldsymbol log 记录 后缀 text P4770 mathcal NOI2018

我永远喜欢数据结构

题目传送门

  • 给出字符串 \(s\) 以及 \(q\) 个询问,第 \(i\) 个询问给出一个串 \(t_i\) 以及一个区间 \([l_i,r_i]\)。

  • 记 \(s[l,r]\) 为字符串 \(s\) 第 \(l\) 位到第 \(r\) 位字符顺次拼接而成的子串。形式化地,\(s[l,r]=\overline{s_ls_{l+1}\dots s_r}\)。

  • 对于每个询问,求 \(t_i\) 有多少种本质不同的子串没有在 \(s[l_i,r_i]\) 中出现。

  • \(|s|\le 5\times 10^5,q\le 10^5,\sum\limits_{i=1}^q|t_i|\le 10^6\)。

  • \(\text{5.00 s / 768.00 MB}\)。

神仙字符串题。

首先把所有字符串用特殊字符接起来,得到一个大串 \(S\)。对 \(S\) 进行后缀排序。这样不改变任意两个后缀的 \(\text{LCP}\)。

对于每一组询问,考虑容斥,即用 \(t_i\) 中的本质不同子串个数减去在 \(s[l_i,r_i]\) 中出现过的。

前半部分是平凡的,即按排名考虑每一个后缀带来的本质不同子串个数,根据经典结论就是这个后缀的前缀数减去它的 \(\text{height}\)。

至于后半部分,同样这样考虑每个后缀带来的本质不同子串中有多少个在 \(s[l_i,r_i]\) 中出现。我们发现若一个后缀 \(\boldsymbol{t_i[j,e]}\) 在 \(\boldsymbol{s[l_i,r_i]}\) 中出现,则 \(\boldsymbol{t_i[j,e-1]}\) 也在 \(\boldsymbol{s[l_i,r_i]}\) 中出现。所以可以考虑二分这个最大的结束位置 \(e\)。判断 \(t_i[j,e]\) 是否在 \(s[l_i,r_i]\) 中出现就是判断是否存在一个位置 \(k\) 使得 \(k\in[l_i,r_i-e+j]\) 且 \(|\text{LCP}(S[k,|S|],t_i[j,e])|\ge e-j+1\)。

二分出排名区间,主席树二维数点检查即可。得到这个值后,\(t_i[j,j+\text{height}_j]\sim t_i[j,e]\) 这些本质不同子串在 \(s[l_i,r_i]\) 中出现,直接减去个数即可。

但是这样回答单组询问的时间复杂度为 \(\mathcal{O}(|t_i| \log |S|\log |t_i|)\),无法接受。

思考一下二分的目的,我们想要对于 \(t_i\) 的每个后缀,得到一个最大的长度 \(L_j\),使得 \(t_i[j,j+L_j-1]\) 在 \(s[l_i,r_i]\) 中出现。

我们发现一个关键性质,那就是 \(\boldsymbol{L_j\ge L_{j-1}-1}\)。因为这两个后缀只差了开头的这一位。

我们可以类似于 \(\text{height}\) 数组那样,用一个指针 \(k\) 表示当前 \(t_i[j,j+k-1]\) 在 \(s[l_i,r_i]\) 中出现,检查是否可行时仍然二分排名区间 + 主席树。若可行则 \(k\) 右移。

由于最多递减 \(\mathcal{O}(|t_i|)\),因此 \(k\) 最多移动 \(\mathcal{O}(|t_i|)\) 次,这样单组询问的时间复杂度就是 \(\mathcal{O}(|t_i|\log |S|)\)。

综上,我们得到了一个时间、空间复杂度均为 \(\mathcal{O}(|S|\log |S|)\) 的做法。

提交记录(\(\color{limegreen}\bf Accepted\space100\),\(\bf{4.62\, s / 606.29\, MB}\)) 代码

标签:子串,boldsymbol,log,记录,后缀,text,P4770,mathcal,NOI2018
From: https://www.cnblogs.com/MnZnOIerLzy/p/17870822.html

相关文章

  • CF1037H Security 做题记录
    搬的学习笔记,之前没想过要新开一篇。题目传送门(CF)给出一个字符串\(s\),有\(q\)次询问,第\(i\)次询问给出\(l_i,r_i,t_i\),求一个字典序最小的字符串\(str\),使得它是\(s[l_i,r_i]\)的子串,且\(str>t_i\)。\(|s|\le10^5\),\(\sum\limits_{i=1}^q|t_i|,q\le2\times10......
  • 记录--原来前端部署这么简单
    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助前言有个朋友说前端技能大家大部分都会,就是部署项目这一块经验都比较稀缺,一直很想学一下。所以在这里写一篇简单的从零开始部署前端项目的全过程,感兴趣的掘友们或者想自己搭建项目部署的可以看一下这篇。环境搭......
  • pytorch 学习记录——计算图
    1.pytorch的计算图是动态更新的(tensorflow是静态计算图),数据流向可以是双向的。2.pytorchvariable(用于封装tensor,便于自动求导的变量类型,在pytorch0.4.0之后版本已被并入tensor)基本属性:data,dtype,shape,device,requires_grad,is_leaf,grad,grad_fn3.is_leaf是否为叶子节点:用户创......
  • 问题记录 <Latex 使用bibliography命令,引用文献中包含中文生僻字>
    问题描述LaTeX使用\bibliography和.bib设置参考文献时,中文生僻字无法显示。解决方式下载字体;将simsun.ttf文件放到.tex同一文件夹下;导言部分添加:%%解决生僻字问题,使用自定义命令\usepackage{ctex}\setCJKfamilyfont{myfont}{simsun.ttf}\newcommand{\MyFont}{\CJKfamil......
  • QT-对于MVC中典型QTreeView简单使用参考记录
    //创建以ui文件中对应View为载体的model<-此处使用QStandardItemModel(比较常用)QStandardItemModel*model=newQStandardItemModel(ui->treeView);model->setHorizontalHeaderLabels(QStringList()<<QStringLiteral("国家")<<QStringLiteral("省份"......
  • AOP-@Around环绕增强-理解问题-测试-记录
    来源自定义注解测试切面环绕时,接口测试返回空白。理解关键在于:环绕增强后走的是切面类中的方法,你不给返回值(习惯void)就是空白=-=。@Around它可以包围一个方法或函数的执行,并在执行前后提供额外的逻辑。使用@Around注解,你可以定义一个通知(advice),该通知在目标方法执行之前和......
  • 使用 logger 命令记录工作日常
    配置指定local6.warning写到日志文件/var/log/work.log,命令:echo"local6.warning/var/log/work.log">/etc/rsyslog.d/55-work.conf重启服务systemctlrestartrsyslog测试命令logger-plocal6.warningaaa验证cat/var/log/work.log,显示如下:Dec111:41:2......
  • i18n使用记录
     ......
  • airScript学习记录2
    ###元组就是不能修改的列表,用()##a=(2,3,432,'adfa')##print(a[3])###修改元组,,把元组转化为列表,用内置函数list()##s=list(a)##s[3]='baba'##print(s[3])##字典可以存储任意数据类型##字典是以键值对的形式存在,键一般是不重复的,如果重复,最后一个值会替代前......
  • linux学习记录(tmux、vim) 9.23
    tmux和vim1、tmux(1)分屏(2)允许把terminal断开之后,继续运行top命令,类似windows的任务管理器,显示各进程运行状况写一个文档或者代码的时候,在tmux里面写,不用担心断网tmux开一堆---->session开一堆(常用)---->window开一堆---->pane(常用)---->shell每一个pane都会打开一......