前置知识

首先你得会manacher,并理解manacher为什么是对的(不用理解为什么它是$O(n)$,这个大概记住就好了,不过理解了更方便做$PAM$的题)

什么是回文自动机?

回文自动机(Palindrome Automaton),是一类有限状态自动机,能识别一个字符串的所有回文子串

它可简化构建出回文树

回文自动机的构造

网上资料很多,不拿出来一步步说了,说一下数组意义、放个板子

$len[u]$表示节点$u$代表的回文串的长度

$ch[u][c]$代表在$u$的回文串两端添加字符$c$得到的新回文串节点

$fail[u]$表示节点$u$的回文串的最长的回文后缀所在的节点

char s[300010];
int n;
//这个板子里面的num表示当前节点的回文串出现了几遍
namespace pam{
int fail[300010],num[300010],len[300010],ch[300010][26],last,cnt;
inline int newnode(int w){len[++cnt]=w;return cnt;}
void init(){
s[0]=-1;cnt=-1;fail[0]=1;last=0;
newnode(0);newnode(-1);//插入两个根节点,设置fail
}
inline int getfail(int cur,int pos){
while(s[pos-len[cur]-1]!=s[pos]) cur=fail[cur];//跳fail
return cur;
}
void insert(int x){
int c=(s[x]-'a'),cur=getfail(last,x);
if(!ch[cur][c]){//新建节点
int now=newnode(len[cur]+2);
fail[now]=ch[getfail(fail[cur],x)][c];
ch[cur][c]=now;
}
num[last=ch[cur][c]]++;
}
}

几个容易写错的点:

fail初始化的时候,如果多组数据并且在newnode里面初始化信息,那么在init的时候记得把fail放到newnode后面

插入的时候函数传进去的是位置

newnode是len[cur]+2不是+1

一些拓展

节点上

首先显然可以统计这个节点的回文串出现次数

统计次数的时候还要加上$fail$树上子树内的所有节点的出现次数

对于一类回文串拥有某个和其$fail$树有关的性质的题目,可以记录一个$trans$,和跳$fail$一样跳,最后用$bfs$来做$dp$或者递推

关于求最小回文串分解

这个问题是问可以把一个字符串分解成最少多少个回文串

解决的方法:

考虑一个显然的$dp$:$dp[i]=dp[j-1]+1 (s[i...j]=palindrome)$

记录一个$anc[u]$

如果$len[u]-len[fail[u]]==len[fail[u]]-len[fail[fail[u]]]$,那么$anc[u]=anc[fail[u]]$

否则$anc[u]=u$

对于$u$的所有跳上去的$anc$集合$S$,我们发现,这个集合中的元素构成一个等差数列,相邻的两项差代表一种从当前点前面递推到当前点的回文串长度

对于每个回文树节点记录$tmp[u]=min(tmp[i-len[anc[u]],tmp[fail[u]])$,然后用这个$tmp[u]+1$来更新当前节点的$dp$,然后$u=fail[anc[u]]$往上跳,直到到达根

证明网上有论文,这里放个代码

inline void insert(int x){
int c=s[x]-'a',cur=getfail(last,x);
val[x]=1e9;
if(!ch[cur][c]){
int now=newnode(len[cur]+2);
fail[now]=ch[getfail(fail[cur],x)][c];
ch[cur][c]=now;
anc[now]=((fail[now]>1&&len[now]-len[fail[now]]==len[fail[now]]-len[fail[fail[now]]])?anc[fail[now]]:now);
}
last=ch[cur][c];
for(cur=ch[cur][c];cur>1;cur=fail[anc[cur]]){
tval[cur]=val[x-len[anc[cur]]];
tpos[cur]=x-len[anc[cur]];
if(anc[cur]!=cur&&tval[fail[cur]]<tval[cur]) tval[cur]=tval[fail[cur]],tpos[cur]=tpos[fail[cur]];
if(val[x]>tval[cur]+1) val[x]=tval[cur]+1,pos[x]=tpos[cur];
}
}

省选算法学习-回文自动机 && 回文树的更多相关文章

  1. Palindromic Tree 回文自动机-回文树 例题+讲解

    回文树,也叫回文自动机,是2014年被西伯利亚民族发明的,其功能如下: 1.求前缀字符串中的本质不同的回文串种类 2.求每个本质不同回文串的个数 3.以下标i为结尾的回文串个数/种类 4.每个本质不同 ...

  2. manacher算法学习(求最长回文子串长度)

    Manacher总结 我的代码 学习:yyb luogu题目模板 xzy的模板 #include<iostream> #include<cstdlib> #include< ...

  3. 省选算法学习-数据结构-splay

    于是乎,在丧心病狂的noip2017结束之后,我们很快就要迎来更加丧心病狂的省选了-_-|| 所以从写完上一篇博客开始到现在我一直深陷数据结构和网络流的漩涡不能自拔 今天终于想起来写博客(只是懒吧.. ...

  4. 省选算法学习-插头dp

    插头dp?你说的是这个吗? 好吧显然不是...... 所谓插头dp,实际上是“基于连通性的状态压缩dp”的简称,最先出现在cdq的论文里面 本篇博客致力于通过几道小小的例题(大部分都比较浅显)来介绍一 ...

  5. 省选算法学习-BSGS与exBSGS与二次剩余

    前置知识 扩展欧几里得,快速幂 都是很基础的东西 扩展欧几里得 说实话这个东西我学了好几遍都没有懂,最近终于搞明白,可以考场现推了,故放到这里来加深印象 翡蜀定理 方程$ax+by=gcd(a,b)$ ...

  6. 省选算法学习-dp优化-四边形不等式

    嗯......四边形不等式的确长得像个四边形[雾] 我们在dp中,经常见到这样一类状态以及转移方程: 设$dp\left[i\right]\left[j\right]$表示闭区间$\left[i,j\ ...

  7. 算法学习——从bzoj2286开始的虚树学习生活

    [原创]转载请标明原作者~ http://www.cnblogs.com/Acheing/ 题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2 ...

  8. 【算法学习】【洛谷】树链剖分 & P3384 【模板】树链剖分 P2146 软件包管理器

    刚学的好玩算法,AC2题,非常开心. 其实很早就有教过,以前以为很难就没有学,现在发现其实很简单也很有用. 更重要的是我很好调试,两题都是几乎一遍过的. 介绍树链剖分前,先确保已经学会以下基本技巧: ...

  9. 数据结构和算法学习笔记十五:多路查找树(B树)

    一.概念 1.多路查找树(multi-way search tree):所谓多路,即是指每个节点中存储的数据可以是多个,每个节点的子节点数也可以多于两个.使用多路查找树的意义在于有效降低树的深度,从而 ...

随机推荐

  1. python格式化输出的方式汇总

    %% 百分号标记 #就是输出一个%%c 字符及其ASCII码%s 字符串%d 有符号整数(十进制)%u 无符号整数(十进制)%o 无符号整数(八进制)%x 无符号整数(十六进制)%X 无符号整数(十六 ...

  2. Centos下使用Docker部署asp.net core项目

    本文讲述 CentOS 系统 Docker 中部署 asp.net core开源项目 abp 的过程 步骤 1. 拉取 asp.net core 基础镜像 docker pull microsoft/ ...

  3. 百度站长针对SEO人员关系的问题的一些解答

    自然排名是全部由机器完成还是存在人工干预? 夫唯:第一个就是说经常好不容易找到了一些新的想法,用我们这些草根的话讲找到了百度的漏洞,好不容易排名上去了,过两天就会波动.有些人就怀疑说在百度的整体算法里 ...

  4. LVM(扩展)

    LVM(扩展)======================== [root@aminglinux newdir]# fdisk -l /dev/sdb 磁盘 /dev/sdb:10.7 GB, 107 ...

  5. manjaro安装teamviewer实现远程连接

    不要安装库里面的这两个版本,安装后桌面快捷方式和命令行运行都正常显示窗口,但没有teamviewer ID和随机密码 12.x版本也不用下载尝试了 ➜ ~ teamviewer Init...Chec ...

  6. Codeforces Round #460 (Div. 2): D. Substring(DAG+DP+判环)

    D. Substring time limit per test 3 seconds memory limit per test 256 megabytes input standard input ...

  7. 栈--数据结构与算法Javascript描述(4)

    栈 Stack 概念 栈是一种高效的数据结构,数据只能在栈顶添加或者删除,所以这样的操作很快,而且容易实现.栈的使用遍布程序语言的方方面面,从表达式求值到处理函数调用. 栈是一种特殊的列表,栈内的元素 ...

  8. 一行代码将两个列表拼接出第三个列表(两个可迭代对象相加产生第三个可迭代对象)--map()方法

    map()方法 map(func, *iterables) --> map object lambda方法: lambda  参数 :返回值 a = map(',7]) print(list(a ...

  9. 笔记-Python-language reference-5.the import system

    笔记-Python-language reference-5.the import system 前言 经常用到import,module,对其中的机制及原理有一定的了解,但没有将各种信息前后连通起来 ...

  10. Android MultiType第三方库的基本使用和案例+DiffUtil的简单用法

    1.MultiType简单介绍 1.1.MultiType用于比较复杂的页面. 如下图,今日头条用到了MultiType处理各种复杂的页面.    这种还是比较简单的类型.因为一个页面也就这种类型. ...