Palindromic Tree。中译过来就是——回文树。

那么这个回文树有何功能?

假设我们有一个串S,S下标从0开始,则回文树能做到如下几点:

1.求串S前缀0~i内本质不同回文串的个数(两个串长度不同或者长度相同且至少有一个字符不同便是本质不同)

2.求串S内每一个本质不同回文串出现的次数

3.求串S内回文串的个数(其实就是1和2结合起来)

4.求以下标i结尾的回文串的个数

那么我们该如何构造回文树?

首先我们定义一些变量。

1.len[i]表示编号为i的节点表示的回文串的长度(一个节点表示一个回文串)

2.next[i][c]表示编号为i的节点表示的回文串在两边添加字符c以后变成的回文串的编号(和字典树类似)。

3.fail[i]表示节点i失配以后跳转不等于自身的节点i表示的回文串的最长后缀回文串(和AC自动机类似)。

4.cnt[i]表示节点i表示的本质不同的串的个数(建树时求出的不是完全的,最后count()函数跑一遍以后才是正确的)

5.num[i]表示以节点i表示的最长回文串的最右端点为回文串结尾的回文串个数。

6.last指向新添加一个字母后所形成的最长回文串表示的节点。

7.S[i]表示第i次添加的字符(一开始设S[0] = -1(可以是任意一个在串S中不会出现的字符))。

8.p表示添加的节点个数。

9.n表示添加的字符个数。

一开始回文树有两个节点,0表示偶数长度串的根和1表示奇数长度串的根,且len[0] = 0,len[1] = -1,last = 0,S[0] = -1,n = 0,p = 2(添加了节点0、1)。

假设现在我们有串S = abbaabba。

首先我们添加第一个字符'a',S[++ n] = 'a',然后判断此时S[n - len[last] - 1]是否等于S[n],即上一个串-1的位置和新添加的位置是否相同,相同则说明构成回文。否则,last = fail[last]。此时last = 0,我们发现S[1 - 0 - 1] != S[1],所以last = fail[last] = 1,然后我们发现S[1 - (-1) - 1] == S[1](即自己等于自己,所以我们让len[1]等于-1可以让这一步更加方便)。

令cur等于此时的last(即cur = last = 1),判断此时next[cur]['a']是否已经有后继,如果next[cur]['a']没有后继,我们就进行如下的步骤:新建节点(节点数p++,且之后p = 3),并让now等于新节点的编号(now = 2),则len[now] = len[cur] + 2(每一个回文串的长度总是在其最长子回文串的基础上在两边加上两个相同的字符构成的,所以是+2,同时体现出我们让len[1] = -1的优势,一个字符自成一个奇回文串时回文串的长度为(-1) + 2 = 1)。然后我们让fail[now] = next[get_fail ( fail[cur] )]['a'],即得到fail[now](此时为fail[2] = 0),其中的get_fail函数就是让找到第一个使得S[n - len[last] - 1] == S[n]的last。然后next[cur]['a'] = now。

当上面步骤完成后我们让last = next[cur][c](不管next[cur]['a']是否有后继),然后cnt[last] ++。

此时回文树为下图状态:


现在我们添加第二个字符字符'b'到回文树中:

继续添加第三个字符'b'到回文树中:


继续添加第四个字符'a'到回文树中:


继续添加第五个字符'a'到回文树中:


继续添加第六个字符'b'到回文树中:

继续添加第七个字符'b'到回文树中:


继续添加第八个字符'a'到回文树中:

到此,串S已经完全插入到回文树中了,现在所有的数据如下:

然后我们将节点x在fail指针树中将自己的cnt累加给父亲,从叶子开始倒着加,最后就能得到串S中出现的每一个本质不同回文串的个数。

构造回文树需要的空间复杂度为O(N*字符集大小),时间复杂度为O(N*log(字符集大小)),这个时间复杂度比较神奇。如果空间需求太大,可以改成邻接表的形式存储,不过相应的要牺牲一些时间。

总的来说,这是一个很好的算法~

模版代码:

struct palindromic_tree{int Next[Maxn][26] ;int fail[Maxn] ;int cnt[Maxn] ;int num[Maxn] ;int len[Maxn] ;int s[Maxn] ;int last ;int n, p ;int newNode (int k){for (int i = 0; i < 26; i++) Next[p][i] = 0 ;cnt[p] = 0 ;num[p] = 0 ;len[p] = k ;return p++ ;}void init(){p = 0 ;newNode(0) ;newNode(-1) ;last = 0 ;n = 0 ;s[n] = -1 ;fail[0] = 1 ;}int get_fail (int x){while (s[n - len[x] - 1] != s[n]) x = fail[x] ;return x ;}void add (int c){c -= 'a' ;s[++n] = c ;int cur = get_fail(last) ;if (!Next[cur][c]){int Now = newNode(len[cur] + 2) ;fail[Now] = Next[get_fail(fail[cur])][c] ;Next[cur][c] = Now ;num[Now] = num[fail[Now]] + 1 ;}last = Next[cur][c] ;cnt[last]++ ;}void Count(){for (int i = p - 1; i >= 0; i--){cnt[fail[i]] += cnt[i] ;}}
}Tree;

Palindromic Tree——回文树(回文自动机)相关推荐

  1. 回文树/回文自动机 引入

    回文树/回文自动机引入 在介绍这种数据结构之前,我们来回顾一下处理字符串的一些武器: 1.KMP.AC自动机 2.后缀三姐妹(后缀树,后缀数组,后缀自动机) 3.字符串hash 4.字符串dp 5.m ...

  2. 回文树(回文自动机) - URAL 1960 Palindromes and Super Abilities

     Palindromes and Super Abilities Problem's Link:  http://acm.timus.ru/problem.aspx?space=1&num=1 ...

  3. 「学习笔记」回文树/回文自动机(Palindromic Tree)

    引入 有时候题目要求一些这样的问题 1. 求以串 s s s 本质不同的回文串个数(即长度不同或长度相同且至少有一个字符不相同的字符串) 2. 求以位置i" role="prese ...

  4. 回文树/回文自动机学习

    len[i]:节点i的回文串的长度 next[i][c]:节点i的回文串在两边添加字符c以后变成的回文串的编号 fail[i]:指向i的最长回文后缀且不为i cnt[i]:节点i表示的回文串在S中出现 ...

  5. Palindromic Tree——回文树【处理一类回文串问题的强力工具】

    今天我们来学习一个神奇的数据结构:Palindromic Tree.中译过来就是--回文树. 那么这个回文树有何功能? 假设我们有一个串S,S下标从0开始,则回文树能做到如下几点: 1.求串S前缀0~ ...

  6. 回文树介绍(Palindromic Tree)

    简介 回文树是由Mikhail Rubinchik大神发明的,在Petrozavodsk Summer Camp 2014上首次提出来,是一个很新的数据结构,目前相关资料比较少. 顾名思义,回文树是一 ...

  7. 回文串问题的克星——Palindrome Tree(回文树)/Palindrome Automaton(回文自动机)学习小记

    前言 最近B组有一道我不会的题,赶紧学习. 简介 我们知道,Manacher算法可以在 O(n) O ( n ) O(n)的时间内求出以每个位置为中心的最长回文串(虽然我昨天还不知道Manacher算 ...

  8. 回文树或者回文自动机,及相关例题

    回文树简述 在大部分说法中,回文树与回文自动机指的是一个东西: 回文树是对一个字符串,基于自动机思想构建的处理回文问题的树形结构: 回文树是对着一个单串建立的: 于是他主要用于计数(回文子串种类及个数 ...

  9. BZOJ2565 最长双回文子串 回文自动机,回文树

    bzoj2565: 最长双回文串 题意 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为"abc",逆序为"cba" ...

最新文章

  1. Android AnimationUtils (动画)的使用
  2. MTK tee.img的打包原理介绍
  3. 英特尔在中国投资55亿美元非易失性存储项目投产
  4. python parser count_8 个 Python 实用脚本,早掌握早下班!
  5. SQL获取变量类型以及变量最大长度
  6. 理解 python 装饰器
  7. 不格式化改U盘文件系统格式
  8. mysql查询并计算单价_数据库实验:统计查询和组合查询图书(书号,书名,作者编号,价格,出版社编号) 作者(编号,姓名,电话)出版社(编号,出版...
  9. 渗透测试 QA 收集
  10. 每日英语--Week6
  11. 乘法鉴相器的matlab仿真,Matlab中基于dq变换的锁相环仿真研究
  12. 关于微博的发表框计数规则及jq实现
  13. ubuntu QT Creator Fatal IO error 2 (没有那个文件或目录) on X server :0
  14. 企业微信应用授权/静默登录
  15. 技巧分享:视频配音怎么制作?(内附3种配音教程)
  16. 基于ECS构建微信公众号管理系统
  17. 趣小面,陆正耀的另一副底牌
  18. 测序总结,高通量测序名词
  19. 旅游自助管理信息系统概要设计规格 .
  20. 破冰船是怎么破冰的?和你想到一点不一样,6米高的冰墙直接就撞

热门文章

  1. Android——动画的实现
  2. 外地人一年内直接落户上海
  3. react中类组件this的指向问题
  4. 张一鸣:每个逆袭的年轻人,都具备的底层能力
  5. react-native 拨打电话
  6. Android IPC 机制详解:IBinder
  7. 金色传说:SAP-BAPI-BAPI_GOODSMVT_CREATE创建物料凭证bapi的使用及参数值讲解
  8. 传统特征提取方法总结
  9. Android 8.1输入法配置
  10. 2022广西省安全员C证上岗证题目及在线模拟考试