原文链接www.cnblogs.com/zhouzhendong/p/PAM.html

前置知识

无。

(强行说和KMP有关也是可以的……)

关于回文串的一些性质

1. 一个长度为 n 的字符串最多有 n 个本质不同的回文子串。

2. 对于一个字符串 S,如果在其之后新插入一个字符,那么最多产生一种新的回文子串。

 证明:

  假设加入这个字符之后得到的最长回文后缀为 T,那么对于长度小于 T 的任何回文后缀,它们必然在更前面的位置出现过。如图所示:

    

  所以只有 T 可能是新的回文子串。

构造PAM

  记 len[x] 表示节点 x 代表的回文串长度,设 Fail[x] 表示“代表 节点 x 所代表的回文串的最长回文后缀 的节点”。(注意这里的最长回文后缀是指长度小于原串的最长回文后缀,和后面提到的意义有差别)

  设 Next[x][c] 表示节点 x 所代表的字符串在前后都加上一个字符 c 之后所到达的状态。则必然有 len[x] + 2 = len[Next[x][c]] 。

  首先,我们建两个节点 A 和 B 。设 len[A] = -1, len[B] = 0 。

  于是长度为 1 的回文串就可以有 A 走转移边到达。

  接下来考虑如何构建 PAM 。

  考虑增量法,在串 s 后面加入一个字符 c 后, PAM 变成了怎样?

  假设当前插入的字符是 s[i],字符串 s 的第 k 个字符为 s[k] 。

  设 x 表示 s 的最长回文后缀,那么如果 s[i - len[x] - 1] = s[i] ,那么最长回文后缀就是 Next[x][s[i]];否则不断使 x = Fail[x] ,直到满足条件就找到了 s 的最长回文后缀。

  找到之后,如果 Next[x][s[i]] 这个节点已经存在,那么什么也不用干;否则,我们新建一个节点代表 Next[x][s[i]] , len[Next[x][s[i]]] = len[x] + 2 ,那么如何求 Fail[Next[x][s[i]]] ?

  考虑找到使 x = Fail[x] ,末尾加入字符 s[i] 之后,再找一次最长回文后缀即可。

模板

namespace PAM{
int len[N],Fail[N],Next[N][26];
int cnt;
void init(){
cnt=2;
len[1]=-1,Fail[1]=1;
len[2]=0,Fail[2]=1;
clr(Next);
}
void build(char *s,int n){
init();
s[0]='*';
int x=1;
for (int i=1;i<=n;i++){
while (s[i-len[x]-1]!=s[i])
x=Fail[x];
int c=s[i]-'a';
if (Next[x][c])
x=Next[x][c];
else {
int y=Next[x][c]=++cnt;
len[y]=len[x]+2;
if (len[y]==1)
Fail[y]=2;
else {
x=Fail[x];
while (s[i-len[x]-1]!=s[i])
x=Fail[x];
Fail[y]=Next[x][c];
}
x=y;
}
}
}
}

模板题

UOJ#103. 【APIO2014】Palindromes

传送门:http://uoj.ac/problem/103

回文自动机(PAM) 学习笔记的更多相关文章

  1. 回文树/回文自动机(PAM)学习笔记

    回文树(也就是回文自动机)实际上是奇偶两棵树,每一个节点代表一个本质不同的回文子串(一棵树上的串长度全部是奇数,另一棵全部是偶数),原串中每一个本质不同的回文子串都在树上出现一次且仅一次. 一个节点的 ...

  2. 回文树(回文自动机PAM)小结

    回文树学习博客:lwfcgz    poursoul 边写边更新,大概会把回文树总结在一个博客里吧... 回文树的功能 假设我们有一个串S,S下标从0开始,则回文树能做到如下几点: 1.求串S前缀0~ ...

  3. 回文自动机pam

    目的:类似回文Trie树+ac自动机,可以用来统计一些其他的回文串相关的量 复杂度:O(nlogn) https://blog.csdn.net/Lolierl/article/details/999 ...

  4. 回文自动机(PAM) 入门讲解

    处理回文串,Manacher算法也是很不错,但在有些问题的处理上比较麻烦,比如求本质不同的子串的数量还需要结合后缀数组才能解决.今天的们介绍一种能够方便的解决关于回文串的问题的算法--PAM. 一些功 ...

  5. 【bzoj3676】[Apio2014]回文串 —— 回文自动机的学习

    写题遇上一棘手的题,[Apio2014]回文串,一眼看过后缀数组+Manacher.然后就码码码...过是过了,然后看一下[Status],怎么慢这么多,不服..然后就搜了一下,发现一种新东西——回文 ...

  6. 省选算法学习-回文自动机 && 回文树

    前置知识 首先你得会manacher,并理解manacher为什么是对的(不用理解为什么它是$O(n)$,这个大概记住就好了,不过理解了更方便做$PAM$的题) 什么是回文自动机? 回文自动机(Pal ...

  7. 洛谷P5496 回文自动机【PAM】模板

    回文自动机模板 1.一个串的本质不同的回文串数量是\(O(n)\)级别的 2.回文自动机的状态数不超过串长,且状态数等于本质不同的回文串数量,除了奇偶两个根节点 3.如何统计所有回文串的数量,类似后缀 ...

  8. URAL 2040 Palindromes and Super Abilities 2 (回文自动机)

    Palindromes and Super Abilities 2 题目链接: http://acm.hust.edu.cn/vjudge/contest/126823#problem/E Descr ...

  9. 【XSY2715】回文串 树链剖分 回文自动机

    题目描述 有一个字符串\(s\),长度为\(n\).有\(m\)个操作: \(addl ~c\):在\(s\)左边加上一个字符\(c\) \(addr~c\):在\(s\)右边加上一个字符 \(tra ...

  10. 字符串数据结构模板/题单(后缀数组,后缀自动机,LCP,后缀平衡树,回文自动机)

    模板 后缀数组 #include<bits/stdc++.h> #define R register int using namespace std; const int N=1e6+9; ...

随机推荐

  1. idea 排除编译 参考

    参考自 : https://www.bbsmax.com/A/LPdoYLkGJ3/

  2. Java基础--面向对象编程2(封装)

    1.封装的定义: 封装:将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问. 2.  为什么需要封装?封装的作用和含义? 首先思考一个问题:当我们要 ...

  3. airflow1.10时区修改

    https://blog.csdn.net/crazy__hope/article/details/83688986

  4. 实现IOC功能的简单Spring框架

    需求分析 设计一个含有IOC的简单Spring,要求含有对象注册.对象管理以及暴露给外部的获取对象功能. 项目设计 对于注册的对象用一个类BeanInfo来描述其信息,包括对象标识.全类名以及属性名与 ...

  5. ES6.3.2 副本失败处理

    ES6.3.2 副本失败处理 副本的失败处理对理解ES的数据副本模型很有帮助.在ES6.3.2 index操作源码流程的总结中提到:ES的写操作会先写主分片,然后主分片再将操作同步到副本分片.本文给出 ...

  6. 如何在Eclipse中创建web项目并使用tomcat8 运行servlet开发简单的动态网页?

    今天花了一天时间.因为用eclipse没多久,不是很熟悉使用,看的教程又是使用myeclipse的,但是eclipse相对没有myeclipse灵活,所以在网上找了很多资料,最后算是可以实现了.新手可 ...

  7. github 远程库

    一.在 Github 创建 django 项目时:先在本地创建项目,然后设置为本地仓库,再与远程仓库关联 在 Git Bash 进入django项目目录,输入命令git init,此时这个目录变成Gi ...

  8. day08 文件操作

    1.三种字符串: (1)u'' 普通字符串 ---> u'abc' ---> 默认的文本方式,以字符作为文本的输出方式 (2)b'' 二进制字符串 ---> b'ASCII码' -- ...

  9. 理解 Linux 的硬链接与软链接【转】

    转自:https://www.ibm.com/developerworks/cn/linux/l-cn-hardandsymb-links/index.html 从 inode 了解 Linux 文件 ...

  10. Gitlab_ansible_jenkins三剑客④jenkins安装图解及freestyle的简单使用

    java环境准备 # 安装jdk1.8 [root@node02 ~]# rpm -ivh jdk-8u181-linux-x64.rpm vim /etc/profile export JAVA_H ...