PAM学习笔记
想了想 还是要先把字符串的东西先都学完告一段落了再说 时间不多了 加油~。
PAM 回文自动机 比SAM简单到不知道哪里去了。
回文自动机和其他自动机一样有字符集 有状态 有转移。
一个字符串的回文自动机的一个最显然的性质是可以识别一个字符串中所有回文子串 这是最有价值的性质。
特点:有两个根 一个代表偶回文串的根 一个代表奇回文串的根 具体的 每个点 同SAM的节点一样都有len fail t[x][c]数组。
可以说 fail指针是所有字符串自动机的精髓吧... 值得一提的是 奇数根的len为-1 偶数根的len为0。
另外 这里我说一下我对fail的理解 这个就很有意思了这里规定偶数根的标号为0 奇数根的编号为1 偶数根的fail为1 奇数根的fail为1\0
对了,fail在回文自动机里的意思是指最长公共回文后缀。偶数根的fail之所以是1是因为接下来只有奇数根的那个位置能够满足了。
奇数根的fail是无效的 因为只要跳到奇数根就意味着一定是合法的了.
还是采用增量法 来构造这个回文自动机。 考虑 上一次构造出来的节点是 p 当前字符为s[i]
那么显然 我们当前这个节点由于是要加到p的后面的 所以 我们要看 s[i-len[p]-1] 和 s[i]是否是相等的 如果相等那么就可以安排一下p的儿子了。
不相等呢 我们考虑围绕这个p搞一些事情 可能存在其他更小的回文串满足这个性质 那么显然我们对p不断的寻找 然后找到一个p满足上述条件。
一直都不满足?最后会跳到奇数根 就满足了。考虑一下更新的信息 设np是当前新建节点 显然 len[np]=len[p]+2;
fail[np]怎么求呢?fail[np]显然我们继续跳p的fail指针然后找到下一个满足条件的点 就是我们当前的fail[np]了。
这里有好几个小细节 如 如果不存在fail[np]那么这个fail[np]是0 还是1 呢 应该是0的是1的话就不对了因为这个地方其实就是这样的fail如果没有实际的点一般都是0而并非1 这样可以让下一个来的字符先满足长度为2的回文串。
还有一点是 为什么这样做事最长的 归纳一下吧 显然 fail[p]按照定义是最长的 那么 fail[np]在fail[p]下也应该是最长的。
一个细节:我们虽然新建了np但是我们不能直接让p连向np 因为如果p是1的话跳fail会跳到np自己的fail指向自己就不太对了吧...
下面是 一个回文自动机可以表示出一个字符串的所有回文子串的证明:
增量法构造的时 新来一个字符c 可能此时形成了多个回文串我们考虑一下最长的那个回文串是否被建好了 如果最长的已经建好了 说明那些较短的回文串也被建好了,因为这个回文串中肯定是包含其他的回文串的,也就是增量到对应的节点的时候这里指回文串的右边显然已经被构造好了所以得证。
如果最长的没有被建好 那么建出来 然后其他的野已经被建好了 还是回文串的右边在增量的时候...得证.
最后 好像还有人求了一发 trans指针 我不知道这个有啥用 但是这个trans指针还是非常容易求出的.
trans指针:小于等于当前节点长度的一半的最长回文后缀。
显然 当len[p]那么考虑更一般的情况 新建节点np 的trans[np]=? 抓住关键...从trans[p]开始跳fail即可且保证能扩展和len满足要求即可...
PAM其实就这么多的东西我的理解我觉得没有什么偏差...对了边数和点数都是O(n)级别的 点数显然 边数也显然...时间复杂度我不会证明但是是O(n)的...
说完了上面 你可能会惊奇的发现 一个字符串的本质不同的回文子串的个数是O(n)级别的.空间的话觉得不太稳开两倍.
至此完结~ 下面可能会放几道有意思的题目...
[SHOI2011双倍回文](https://www.luogu.com.cn/problem/P4287)
给定一个字符串 求这个字符串的最长双倍回文子串的长度,最长双倍回文子串的定义:长度是4的倍数,前半部分是回文的,后半部分也是回文的,且整体还是回文的.
看起来很不好做的样子... 分析一下性质吧 有意思的是 双倍回文子串的两半都必须是偶回文串 因为不是的话不可能是4的倍数.
解法也就出现了 遍历每一个回文串 惊奇的发现 利用trans指针就可以解决这个问题!由于我们遍历了所有的本质不同字符串所以显然可以求得答案.
[最长双回文串](https://www.luogu.com.cn/problem/P4555)
这道题也很简单 但是却有一些小套路在里面 两端都是回文串 一个比较容易想到的是 枚举断点i 求以i为结尾最长的和以i+1位开头的最长的回文串加起来即可。
这思想在很多题目中都有应用。
[CERC2014 Virus synthesis](https://www.luogu.com.cn/problem/P4762)
多组数据 每组数据给定一个字符集为{A,G,C,T}的字符串T 初始有一个空串 每次可以在串的开头或结尾加上一个字符 或者在串开头或末尾加上一个该串的逆串.
求最小操作次数。显然是不可以二分的,因为构造出这个字符串我们可以直接求出二分再构造无疑是不必要的。
由于是串的逆序 可以发现显然应该是T的回文子串 但是是整个字符串的回文 所以我们肯定是先构造出某个回文串剩下的再暴力构造。
这就又需要我们的trans指针了 好像这样dp下一下就没了...但是 我没想到一个转移啊啊啊
f[i]=min(f[i],f[f(i)]+1)这个转移没写 我想半天以为思路出错了 结果是根本就没有完善好思路 哎.
考虑一个性质 我们不单需要trans指针 也可能是直接的暴力累加过来的...我是dd.
PAM学习笔记的更多相关文章
- 回文树/回文自动机(PAM)学习笔记
回文树(也就是回文自动机)实际上是奇偶两棵树,每一个节点代表一个本质不同的回文子串(一棵树上的串长度全部是奇数,另一棵全部是偶数),原串中每一个本质不同的回文子串都在树上出现一次且仅一次. 一个节点的 ...
- C++学习笔记(2)
本学习笔记是C++ primer plus(第六版)学习笔记.是C++学习笔记(1)的后续.复习C++基础知识的可以瞄瞄. 转载请注明出处http://www.cnblogs.com/zrtqsk/p ...
- Beego学习笔记——Logs
日志处理 这是一个用来处理日志的库,它的设计思路来自于database/sql,目前支持的引擎有file.console.net.smtp,可以通过如下方式进行安装: go get github.co ...
- 后缀自动机&回文自动机学习笔记
在学了一天其实是边学边摆之后我终于大概$get$后缀自动机了,,,就很感动,于是时隔多年我终于决定再写篇学习笔记辽$QwQ$ $umm$和$FFT$学习笔记一样,这是一篇单纯的$gql$的知识总结博, ...
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
- PHP-自定义模板-学习笔记
1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ...
- PHP-会员登录与注册例子解析-学习笔记
1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...
- 2014年暑假c#学习笔记目录
2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...
- JAVA GUI编程学习笔记目录
2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...
随机推荐
- python 三维散点插值 griddata
#三维点插值#在三维空间中,利用实际点的值推算出网格点的值import numpy as np point_grid =np.array([[0.0,0.0,0.0],[0.4,0.4,0.4],[0 ...
- java 面向对象(三十二):泛型一 泛型的理解
1.泛型的概念所谓泛型,就是允许在定义类.接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型.这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量.创建对象时确定 ...
- python 生成器(二):生成器基础(二)惰性实现
简介 设计 Iterator 接口时考虑到了惰性:next(my_iterator) 一次生成一个元素.懒惰的反义词是急迫,其实,惰性求值(lazy evaluation)和及早求值(eager ev ...
- C#/VB.NET 在Word中添加条码、二维码
本文介绍如何通过C# 和VB.NET代码实现在Word文档中添加条码和二维码.代码中将分为在Word正文段落中.页眉页脚中等情况来添加. 使用工具:Free Spire.Office for .NET ...
- 通过PHP工具箱-站点域名管理(创建本地虚拟主机)
工具:php程序员工具箱(网上很多请自己搜索下载) 1.点击其它选项菜单 -> 选择站点域名管理.如下图 2.进入站点域名管理.如下图(初始的时候,站点为空) 3.设置站点管理.如下图 网站域名 ...
- 小程序开发全栈1.2/3/4组件、flex布局、样式
1.2 组件 1.2.1 text组件 编写文本信息,类似于HTTP中的span 1.2.2 view组件 容器,类似于HTTP中的div 1.2.3 image组件 图片显示组件 1.3 页面fle ...
- 怎么理解Python迭代器与生成器?
怎么理解Python迭代器与生成器?在Python中,使用for ... in ... 可以对list.tuple.set和dict数据类型进行迭代,可以把所有数据都过滤出来.如下: ...
- 【Python】Async异步等待简单例子理解
import time def run(coroutine): try: print("") coroutine.send(None) except StopIteration a ...
- three.js 制作魔方
因为之前的几节讲了一些数学方法,例如Vector3.Matrix4.Euler还有Quaternion的知识.所以这篇郭先生就来说说用three.js怎么制作一个魔方.在线案例请点击博客原文 制作魔方 ...
- gerrit安装指南
Gerrit的基本介绍 Gerrit 是一个Git服务器,它基于 git 版本控制系统,使用网页界面来进行审阅工作.Gerrit 旨在提供一个轻量级框架,用于在代码入库之前对每个提交进行审阅,更改将上 ...