【知识总结】回文自动机(Palindrome_Automaton)
参考资料: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;
do
c = getchar();
while (c != EOF && c != '-' && !isdigit(c));
if (c == EOF)
return false;
if (c == '-')
f = true, c = getchar();
do
c = 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();
}
【知识总结】回文自动机(Palindrome_Automaton)的更多相关文章
- 省选算法学习-回文自动机 && 回文树
前置知识 首先你得会manacher,并理解manacher为什么是对的(不用理解为什么它是$O(n)$,这个大概记住就好了,不过理解了更方便做$PAM$的题) 什么是回文自动机? 回文自动机(Pal ...
- URAL 2040 (回文自动机)
Problem Palindromes and Super Abilities 2 (URAL2040) 题目大意 给一个字符串,从左到右依次添加,询问每添加一个字符,新增加的回文串数量. 解题分析 ...
- URAL 2040 Palindromes and Super Abilities 2 (回文自动机)
Palindromes and Super Abilities 2 题目链接: http://acm.hust.edu.cn/vjudge/contest/126823#problem/E Descr ...
- 后缀自动机/回文自动机/AC自动机/序列自动机----各种自动机(自冻鸡) 题目泛做
题目1 BZOJ 3676 APIO2014 回文串 算法讨论: cnt表示回文自动机上每个结点回文串出现的次数.这是回文自动机的定义考查题. #include <cstdlib> #in ...
- [模板] 回文树/回文自动机 && BZOJ3676:[Apio2014]回文串
回文树/回文自动机 放链接: 回文树或者回文自动机,及相关例题 - F.W.Nietzsche - 博客园 状态数的线性证明 并没有看懂上面的证明,所以自己脑补了一个... 引理: 每一个回文串都是字 ...
- BZOJ2160拉拉队排练——回文自动机
题目描述 艾利斯顿商学院篮球队要参加一年一度的市篮球比赛了.拉拉队是篮球比赛的一个看点,好的拉拉队往往能帮助球队增加士气,赢得最终的比赛.所以作为拉拉队队长的楚雨荨同学知道,帮助篮球队训练好拉拉队有多 ...
- BZOJ2084[Poi2010]Antisymmetry——回文自动机
题目描述 对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一样,就称作“反对称”字符串.比如00001111和010101就是反对称的,1001就不是.现在给出一个长度为N的0 ...
- BZOJ2342[Shoi2011]双倍回文——回文自动机
题目描述 输入 输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容. 输出 输出文件只有一行,即:输入数据中字符串的最长双倍回文子串的长度,如果双倍回文 ...
- 【XSY2715】回文串 树链剖分 回文自动机
题目描述 有一个字符串\(s\),长度为\(n\).有\(m\)个操作: \(addl ~c\):在\(s\)左边加上一个字符\(c\) \(addr~c\):在\(s\)右边加上一个字符 \(tra ...
随机推荐
- ubutun 创建左面快捷方式
#http://blog.csdn.net/jizi7618937/article/details/51012552
- Python基础-获取当前目录,上级目录,上上级目录
import os print '***获取当前目录***' print os.getcwd() print os.path.abspath(os.path.dirname(__file__)) pr ...
- Spring AOP 学习(五)
1. 使用动态代理实现AOP package com.atguigu.spring.aop; import java.lang.reflect.InvocationHandler; import ja ...
- BNUOJ 23905 滑雪
滑雪 Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on UESTC. Original ID: 13096 ...
- noip模拟赛 戏
[问题背景]zhx 和他的妹子(们) 做游戏.[问题描述]考虑 N 个人玩一个游戏,任意两个人之间进行一场游戏(共 N*(N-1)/2 场),且每场一定能分出胜负.现在, 你需要在其中找到三个人构成“ ...
- 质因数分解 2012年NOIP全国联赛普及组
时间限制: 1 s 空间限制: 128000 KB 题目等级 : 青铜 Bronze 题目描述 Description 已知正整数 n是两个不同的质数的乘积,试求出较大的那个质数 . 输入描述 Inp ...
- Ubuntu 16.04安装FTP客户端filezilla
1.安装: sudo apt-get install filezilla 参考: http://os.51cto.com/art/201103/247564.htm
- Qt移动应用开发(二):使用动画框架
Qt移动应用开发(二):使用动画框架 上一篇博客介绍了怎样使用Qt的QML来对屏幕分辨率大小进行适应,其实,不同分辨率的适应是一个很棘手的问题,除了分辨率不同外,宽高比(aspect ratio)也不 ...
- 关于new和malloc以及delete和free能否够混用
/* *1>当申请的空间是内置类型时,delete和free能够混用 *2>当申请的空间是自己定义类型时, * 1>若没有析构函数.delete和malloc能够混用.有 ...
- MySQL用户及数据安全专题
1 简单介绍 1.1 概要 1.2 权限分类 2 加入用户 2.1 语法例如以下: CREATE USER user_specification [, user_specification] ...