参考资料:Palindromic Tree——回文树【处理一类回文串问题的强力工具】(请注意,其中似乎有一些错误)

回文自动机似乎和回文树是同一个东西qwq?

回文自动机(PAM)是一种处理回文串的工具。它的每个结点表示一个本质不同的回文串,转移边\(c\)表示在当前字符串的首尾分别加一个字符\(c\)。

回文自动机由两棵树组成,根结点分别称为\(odd\)和\(even\)。\(even\)表示空串,长度为\(0\),长度为偶数的回文串在它的子树上;\(odd\)表示一个“虚拟”的串,长度为\(-1\),长度为奇数的回文串在它的子树上。\(odd\)的直接儿子表示只有一个字母的回文串。沿着转移边\(c\)走一步就在当前串首尾各加上一个字符\(c\)。和AC自动机类似,一个结点的\(fail\)指针指向它的最长回文真后缀(定义\(fail[even]=odd\))。比如wqwqqwqwq的回文自动机长这样(数字表示结点编号,红箭头表示\(fail\)指针):

我画着画着发现这个字符串里回文串比想象的多

和后缀自动机类似,构造回文自动机也采用每次插入一个字符的方法。设原串是\(S\),当前位置是\(pos\),要加入的字符是\(c\),则可能会多一些以字符\(c\)结尾的回文串。而多的这些字符串可以看成是一个回文串\([a,pos-1]\)满足\(S_{a-1}=c\)后面加一个字符\(c\)。于是要找到最长的这样的回文串\([a,pos-1]\),即从\(pos-1\)这个结点开始爬\(fail\)链,直到\(p\)点满足\(S_{pos-len[p]-1}=S_{pos}\)。爬\(fail\)链最终会到长度为\(-1\)的\(even\),由于\(pos-(-1)-1=pos\),所以这个式子最终一定会成立。这个过程即代码中的\(get\_fail\)函数。

设第一个满足如上条件的点是\(p\)。如果\(p\)已经有了\(c\)字符的转移,则直接增加它的\(cnt\)(该字符串出现次数)即可;如果没有,则新建结点\(q\),\(q\)的长度显然是\(p\)的长度加\(2\),\(q\)的\(fail\)是从\(p\)的\(fail\)往上爬,找到第一个在后面加字符\(c\)仍为回文串的地方(方法同上述\(get\_fail\)),把它加字符\(c\)后转移到的点作为\(q\)的\(fail\)。

注意,如果要统计每个回文串的出现次数(即\(cnt\)),建完后要在\(fail\)树上做一遍树上递推(因为插入的时候只在当前点结尾的最长回文串的结点\(cnt\)上加\(1\)。如果一个串出现了,它的最长回文真后缀一定也出现了)。由于回文自动机是两棵树,所以不需要像后缀自动机求\(Right\)集合大小一样拓扑排序,只要按标号从大到小做即可。

题目:洛谷3649

把每个结点的长度\(len\)乘上出现次数\(cnt\)然后加起来就好了。

代码:

#include <cstdio>
#include <algorithm>
#include <cctype>
#include <cstring>
#include <string>
#define _ 0
using namespace std;namespace zyt
{const int N = 3e5 + 10;template<typename T>inline bool read(T &x){char c;bool f = false;x = 0;doc = getchar();while (c != EOF && c != '-' && !isdigit(c));if (c == EOF)return false;if (c == '-')f = true, c = getchar();doc = getchar();while (isdigit(c));if (f)x = -x;return true;}inline bool read(string &s){static char buf[N];if (scanf("%s", buf) == -1)return false;else{s = buf;return true;}}template<typename T>inline void write(T x){static char buf[20];char *pos = buf;if (x < 0)putchar('-'), x = -x;do*pos++ = x % 10 + '0';while (x /= 10);while (pos > buf)putchar(*--pos);}const int CH = 26;typedef long long ll;string s;namespace Palindrome_Auto_Machine{struct node{int len, cnt, fail, s[CH];}tree[N];int cnt, last, odd, even, pos;char s[N];void init(){last = even = 0, odd = 1, cnt = 1, pos = 0;s[0] = '#';tree[odd].len = -1, tree[even].len = 0;tree[odd].fail = tree[even].fail = odd;}int get_fail(int p){while (s[pos - tree[p].len - 1] != s[pos])p = tree[p].fail;return p;}void insert(const char c){s[++pos] = c;int x = c - 'a', p = get_fail(last);if (!tree[p].s[x]){tree[++cnt].len = tree[p].len + 2;tree[cnt].fail = tree[get_fail(tree[p].fail)].s[x];tree[p].s[x] = cnt;}last = tree[p].s[x];++tree[last].cnt;}void build(const string &str){for (int i = 0; i < str.size(); i++)insert(str[i]);for (int i = cnt; i > 0; i--)tree[tree[i].fail].cnt += tree[i].cnt;}inline ll solve(){ll ans = 0;for (int i = 0; i <= cnt; i++)ans = max(ans, (ll)tree[i].cnt * tree[i].len);return ans;}}int work(){using Palindrome_Auto_Machine::init;using Palindrome_Auto_Machine::build;using Palindrome_Auto_Machine::solve;read(s);init();build(s);write(solve());return (0^_^0);}
}
int main()
{return zyt::work();
}

转载于:https://www.cnblogs.com/zyt1253679098/p/10324742.html

【知识总结】回文自动机(Palindrome_Automaton)相关推荐

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

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

  2. 算法学习:回文自动机

    [定义] [自动机] 参照AC自动机 [前置知识] [AC自动机] [manacher] 其实不学这两个也可以,但是学过之后会更方便理解 [解决问题] 主要解决回文串的问题 能求出   字符串中回文子 ...

  3. 2019ICPC(徐州) - Colorful String(哈希+二分+动态规划/回文自动机)

    题目链接:点击查看 题目大意:给出一个字符串,询问该字符串中的所有回文子串中,各有多少不同的字母 题目分析:这个题题意很简单,在比赛的时候看到字符串第一反应是哈希,哈希+暴力+线段树果不其然的T掉了. ...

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

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

  5. 【回文自动机】bzoj3676 [Apio2014]回文串

    回文自动机讲解!http://blog.csdn.net/u013368721/article/details/42100363 pam上每个点代表本质不同的回文子串.len(i)代表长度,cnt(i ...

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

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

  7. 论如何优雅的处理回文串 - 回文自动机详解

    写在前面 最近无意中看到了这个数据结构,顺便也就学习了一下. 而且发现网上关于这个算法的描述有很多地方是错的,在这里做了一些更正. 处理字符串的算法很多: KMP,E-KMP,AC自动机,后缀三兄弟: ...

  8. BZOJ2342[Shoi2011]双倍回文——回文自动机

    题目描述 输入 输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容. 输出 输出文件只有一行,即:输入数据中字符串的最长双倍回文子串的长度,如果双倍回文 ...

  9. BZOJ4044 Luogu P4762 [CERC2014]Virus Synthesis (回文自动机、DP)

    好难啊..根本不会做..基本上是抄Claris... 题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=4044 (luogu) ...

最新文章

  1. linux shutter截图,Ubuntu中安装Shutter截图工具
  2. matlab中的lower,请问:MATLAB中,有实现Gabor变换的函数吗?
  3. 机器学习实战之决策树
  4. 2020年前端最火的技术是什么?
  5. MDK、keil复制中文注释乱码
  6. Python:matplotlib绘制条形图
  7. 计算机基础与C语言程序设计书籍,C语言程序设计(21世纪高等学校计算机基础实用规划教材)...
  8. 【统计学知识案例实践】—数据分析实战案例
  9. haswell架构_一个月拥有Intel Haswell原型
  10. 小米手机第三方卡刷软件_小米手机MIUI卡刷图文教程
  11. 拼图·面部表情捕捉 | design-ai-lab
  12. jupyter离线包_[伟哥艾路]jupyter实验室包的离线安装,小,AI,之路,Jupyter,jupyterlab
  13. 1999年中国省、自治区的城市规模结构特征的一些数据,可通过聚类分析将这些省、自治区进行分类_BeansSuperman_新浪博客
  14. linux 安装qt5和qtcreator开发工具
  15. 思维导图工具之Mindmeister
  16. IDM UltraEdit编辑器V26.00.0.48 烈火汉化64位版
  17. 计算机省二打字,巧用音频转文字,省去打字烦恼
  18. Eclipse中快捷键Ctrl + Alt + 向上箭头 或者 Ctrl + Alt + 向下箭头与Windows冲突
  19. BUUCTF-MRCTF2020
  20. 基于微信小程序云开(统计学生信息并导出excel)

热门文章

  1. c语言案例——输入一个字符串,将其逆序输出
  2. Python+selenium 自动化-获取当前页面的url地址,打开指定的url地址
  3. 二叉树的前序中序后序递归查找,深度,广度搜索C++实现(VS2017)
  4. DOSbox汇编环境配置
  5. CTFshow 命令执行 web71
  6. 对整个矩阵元素进行计算:最大数、最小数、排序
  7. matlab程序和程序文件
  8. 用递归方法对二叉树进行先序、中序和后序遍历
  9. 【论文阅读和实现】On Spectral Clustering: Analysis and an algorithm【Python实现】
  10. [SOJ1039]Phone Home(深搜,染色问题)