LOJ3123 CTS2019 重复 KMP自动机、DP、多项式求逆
CTS的计数题更完辣(撒花
Orz zx2003,下面的内容在上面的博客基础上进行一定的补充。
考虑计算无限循环之后不存在子串比\(s\)字典序小的串的个数。先对串\(s\)建立KMP自动机,那么对于点\(i\)连出的所有边,只有不是回到起点的字符最大的那条边以及字符比它大的走向起点的边可以走,因为如果走其他边,那么当前匹配的串就会存在一个后缀比\(s\)字典序小。
经过这样的删边后,对于每一个点只有两种边,一种是去往另一个点的边,一种是去往起点的边。如果不考虑去往起点的边,与起点连通的连通块刚好构成一个rho的形状(也就是\(\rho\),即一条从起点开始的链,链底是一个环)。我们考虑在这个rho上计数。
不妨设当前构造的满足条件的串是串\(t\)。有一个引理:设\(a_0 = 0\),\(a_i =\)从KMP自动机上的\(a_{i-1}\)号点开始匹配串\(t\)走到的位置,可以得到一个长度无限的序列\(a\),在序列\(a\)上必定存在一个位置\(x\)满足\(\forall y > x , a_y = a_x\)。
证明:\(a_x\)实质上就是把\(x\)个\(t\)串拼在一起放在KMP自动机上匹配最后到达的节点。因为如果\(t\)合法,那么\(t\)只会走每个点字符最大的一条边和比这个字符更大的回到起点的边,所以将\(x\)个\(t\)串放在现在的KMP自动机上匹配等价于将\(x\)个\(t\)串放在没有删边之前的KMP自动机上匹配,而在后者意义下匹配完到达的节点表示\(x\)个\(t\)串的最长后缀满足它是\(s\)的前缀。当\(x|t|>|s|\),因为在后面加上一个\(t\)相当于在前面加上一个\(t\),而此时加上一个\(t\)不可能对最长后缀的长度产生影响,所以再加上一个\(t\)进行匹配,仍会匹配到之前的节点。
显然这个匹配到的节点是唯一的,所以我们可以枚举这个节点,那么我们需要求的就是长度为\(m\)的路径条数满足起点和终点都是这一个点。
如果从一个节点开始匹配串\(t\),没有经过起点回到自己,那么一定是在rho上转,方案数唯一。
接下来考虑回到起点的情况。考虑一个dp:设\(f_{i,j}\)表示从起点开始走\(i\)步走到节点\(j\)的方案数,这个可以直接做。接下来我们枚举从这个节点沿着\(\rho\)走了多少步回到根,用回到根的方案数乘上从起点经过若干步到达当前节点的方案数贡献答案。
总复杂度\(O(n^2)\)。
接下来使用多项式运算优化上面后半部分计算的复杂度。
上面枚举的路径相当于三个过程:从当前节点开始走到起点->走若干次起点到起点的路径->从起点走到当前节点停下来,而第一个过程和第三个过程合起来等价于先枚举一个从起点开始走回起点的路径,然后再在这条路径上选择一个点作为匹配终点。那么先枚举这条路径,对于一条长度为\(x\)的路径,就有\(x\)种选择匹配终点的方式。
不妨设\(F = \sum\limits_{i=1}^\infty f_ix^i\),其中\(f_i\)表示从起点开始走\(i\)步走回到起点的方案数,这个可以在KMP自动机建立之后计算。那么枚举第一个过程和第三个过程的路径的并,方案数的多项式就是\(x F'\)。接下来再枚举经过了多少次起点,需要乘上多项式\(\sum\limits_{i=0}^\infty F^i = \frac{1}{1 - F}\),那么最终的答案就是\([x^m] (xF' \times \frac{1}{1 - F} + 1)\),最后加上的\(1\)是一个余项。
最新文章
- C段渗透+cain嗅探
- nginx负载均衡基于ip_hash的session粘帖
- MyBatis学习(二)、SQL语句映射文件(1)resultMap
- PSP记录个人项目耗时
- Python使用UUID库生成唯一ID(转)
- Protege A DOT error has occurred错误
- Microsfot SQL Server 2012 日志收缩
- 理解ThreadLocal(一)
- 使用CNN(convolutional neural nets)关键的一点是检测到的面部教程(四):学习率,学习潜能,dropout
- Spring中获取对象
- Linux中如何恢复rm命令误删除的文件之extundelete编译安装及使用
- 在access转sql server指定的转换无效
- VS 附加到进程 加载“附加进程”弹窗很慢
- [JUC-4]ThreadPoolExecutor源码分析
- Installing TensorFlow on Ubuntu or Windows
- Vue 改变数组中对象的属性不重新渲染View的解决方案
- MsSqlserver 查看锁表与解锁
- Qt中的串口编程之一
- laravel + html ajax 多表单字段和图片一起上传
- asp.net 下载的几种方式
热门文章
- MongoDB---如何避免插入重复数据(pymongo)
- SpringBoot导入Excel数据到MySQL数据库
- 数据结构实验之排序四:寻找大富翁(SDUT 3401)
- 浅谈 Miller-Robbin 与 Pollard Rho
- 再见,Eclipse。
- NIO 选择器 Selector
- [C++] const和mutable关键字使用方法
- 单细胞数据整合方法 | Comprehensive Integration of Single-Cell Data
- 【深入学习linux】VMware新建虚拟机教程
- 微信小程序实例:分享给一个人还是分享到群的判断代码