题解 loj2065 「SDOI2016」模式字符串
点分治。
考虑经过当前分治中心\(u\)的点对数量。
这种数点对数的问题,有一个套路。我们可以依次考虑\(u\)的每个儿子,看用当前的儿子,能和之前已经考虑过的所有儿子,组成多少点对。这样所有合法的点对都会被恰好计算一次。
现在搜索\(u\)的一个儿子\(v\)的子树。对子树里的每个点,考虑它到\(u\)的有向路径形成的串。在搜索的过程中,我们每次要在当前串的“开头”处添加一个字符(即把整个串整体右移一位),没有什么好的数据结构可以维护,于是想到哈希。现在我们要判断,当前的串,是否是“若干个\(s\)”的一个前缀;如果是(称这样的节点是合法的),那我们要知道它最后匹配到的“零头”是多长,也即这个“前缀”的长度\(\bmod m\)的余数是多少。具体地,在搜索时,我们维护一个桶\(buc\)。\(buc[i]\)表示有多少个合法的节点\(x\),使得\(x\)到\(u\)的串的长度\(\bmod m=i\)。
这样就维护出了所有的前缀。现在我们想知道,\(v\)的子树内每个合法的前缀,能匹配\(v\)之前的子树内的多少合法的后缀。在搜索时,我们用和维护前缀类似的方法来维护后缀。对后缀,我们把\(s\)整体反转,然后也开一个桶,做和匹配前缀时一样的操作即可。
同样,对于\(v\)子树内的所有合法的后缀,我们也要知道它能匹配\(v\)之前的子树内的多少合法的前缀。(这是因为路径是有向的,因此要拿\(v\)内的前缀匹配一次前面的后缀,再拿\(v\)内的后缀匹配一次前面的前缀)。
现在完成了对\(v\)的子树的搜索,也把\(v\)子树的贡献计入了答案。我们得到了两个桶,分别是\(v\)内所有合法前缀的串长\(\bmod m\)的值为\(i\)的点的数量,和\(v\)内所有合法后缀的串长\(\bmod m\)的值为\(i\)的点的数量。现在,\(v\)这棵子树的身份就从“当前子树”,变成了“当前子树之前的子树”。于是拿这两个\(v\)的桶去分别更新两个“全局桶”即可。
注意,桶的大小是\(\min(m,\text{maxdep}_v)\),在更新全局桶和清空小桶时一定不能直接for到\(m\),否则复杂度就不对了。
除了点分治,其他部分的复杂度是线性的。因此总时间复杂度\(O(n\log n)\)。
题解 loj2065 「SDOI2016」模式字符串的更多相关文章
- loj2065 「SDOI2016」模式字符串
ref不是太懂 #include <iostream> #include <cstring> #include <cstdio> using namespace s ...
- 【LOJ】#2065. 「SDOI2016」模式字符串
题解 按秩合并怎么清数组对我来说真是世纪性难题 我们很熟练地想到点分,如果我们认为某个点到重心是正着读的,由于它的深度固定,它的串也是固定的,我们只要预处理出所有长度正着重复的串,反着重复的串,和它们 ...
- 「SDOI2016」征途 题解
「SDOI2016」征途 先浅浅复制一个方差 显然dp,可以搞一个 \(dp[i][j]\)为前i段路程j天到达的最小方差 开始暴力转移 \(dp[i][j]=min(dp[k][j-1]+?)(j- ...
- liberOJ #2033. 「SDOI2016」生成魔咒 后缀数组
#2033. 「SDOI2016」生成魔咒 题目描述 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1 11.2 22 拼凑起来形成一个魔咒串 [1,2] [1, 2] ...
- [LOJ 2070] 「SDOI2016」平凡的骰子
[LOJ 2070] 「SDOI2016」平凡的骰子 [题目链接] 链接 [题解] 原题求的是球面面积 可以理解为首先求多面体重心,然后算球面多边形的面积 求重心需要将多面体进行四面体剖分,从而计算出 ...
- 【题解】「P6832」[Cnoi2020]子弦
[题解]「P6832」[Cnoi2020]子弦第一次写月赛题解( 首先第一眼看到这题,怎么感觉要用 \(\texttt{SAM}\) 什么高科技的?结果一仔细读题,简单模拟即可. 我们不难想出,出现最 ...
- 「SDOI2016」数字配对
「SDOI2016」数字配对 题目大意 传送门 题解 \(a_i\) 是 \(a_j\) 的倍数,且 \(\frac{a_i}{a_j}\) 是一个质数,则将 \(a_i,a_j\) 质因数分解后,其 ...
- 「SDOI2016」储能表(数位dp)
「SDOI2016」储能表(数位dp) 神仙数位 \(dp\) 系列 可能我做题做得少 \(QAQ\) \(f[i][0/1][0/1][0/1]\) 表示第 \(i\) 位 \(n\) 是否到达上界 ...
- 【题解】「UVA681」Convex Hull Finding
更改了一下程序的错误. Translation 找出凸包,然后逆时针输出每个点,测试数据中没有相邻的边是共线的.多测. Solution 首先推销一下作者的笔记 由此进入>>> ( ...
随机推荐
- row_number over ()排序函数
语法: row_number () over (排序规则) 计算每一行数据在结果集的行数 select ROW_NUMBER() over (order by FSalary) as 排序 ,* ...
- HDU 1035 Robot Motion(dfs + 模拟)
嗯... 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1035 这道题比较简单,但自己一直被卡,原因就是在读入mp这张字符图的时候用了scanf被卡. ...
- 「CF197B Limit」
题目撞名 题目大意: 给出两个函数 \(P(x),Q(x)\). \(P(x)=a_0 \times x^N+a_1 \times x^{N-1}+a_2 \times x^{N-2} \cdots ...
- 01背包第k最优解
附题目链接:Bone Collector II Input The first line contain a integer T , the number of cases.Followed by T ...
- 从npz文件中读取图片并显示的小例子
前提:我把自己的数据集存成了npz的形式,也就是npy的压缩形式.如果电脑上安装了解压软件,双击npz文件的话,会出现每一部分压缩文件的名字例如npz文件的名称为:mnist.npz文件,用好压解压软 ...
- Vue日常报错
报错信息: Error: Cannot find module 'webpack/bin/config-yargs' at Function.Module._resolveFilename (inte ...
- task20160125
http://task.zbj.com/2034844/n15o1.html 百度开放平台--首页>帮助文档首页>Frontia>Android开发指南>个人数据存储 http ...
- node.js中的事件轮询Event Loop
任务队列/事件队列 "任务队列"是一个事件的队列,IO设备完成一项任务,就在"任务队列"中添加一个事件,表示相关的异步任务可以进入"执行栈" ...
- 八大排序算法C++代码实现
八大排序算法 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 我们这里说说八大排序就是内部排序 ...
- IDEA中找不到spring的配置文件,或者不存在某个目录(比如没有src 目录)
比如 项目中src目录找不到了,解决方式为: 这类问题都是设置这儿.