简介
回文树(回文自动机),是解决一类回文串问题的强大数据结构,比
Manacher
扩展了很多功能。
这个数据结构比较新,由来自战斗民族的神犇MikhailRubinchik在2014年的Petrozavodsk夏令营提出。
这个数据结构代码量其实超级少。
必备技能
Manacher
最好会至少一种自动机
分析
回文树严格来讲是由两棵树构成的森林,再加上一堆后缀链(失配链)。其中一棵树代表长度为奇数的回文串,另一棵树代表长度为偶数的回文串。树上每个节点都代表一种与其它节点不同的回文串,所以每个点上都有诸如长度
len
和出现次数
cnt
之类的权值。
后缀链
fail
连向代表以这个点代表的回文串的最长回文后缀的点(有点长,自己断句)。
初始时,偶数树的根节点代表一个空串,长度为
0
,后缀链连向奇数树的根节点。奇数树的根节点则比较神,代表一个被吞掉一个字符的串(是不是很鬼畜???),长度为
插入操作过程中,我们需要记录当前插入的串的最长回文后缀
suf
。设原串为
s
,当我们要加入第
我们找到
x
点后,先判断
由于blog主特别懒,这里就不配图了,大家结合代码理解理解吧。
建完树,我们要重算一次每个回文串出现次数。过程很简单,就是倒序枚举节点,假设枚举到
x
,我们给
然后剩下的就是结合题目乱搞了。
代码实现
注:以下代码对应题目[APIO2014]回文串,也是算法的出处,推荐大家去做一做。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N=300005;
const int C=26;
long long ans;
char str[N];
int n;
struct Palindrome_Tree
{
int next[N][C],cnt[N],fail[N],len[N];
int tot,suf;
int newnode()
{
for (int i=0;i<C;i++)
next[tot][i]=0;
cnt[tot]=0,fail[tot]=0;
return tot++;
}
void init()
{
tot=0;
int p;
len[p=newnode()]=0;
p=fail[p]=newnode();
len[p]=-1;
fail[p]=p;
suf=0;
}
int getfail(int x,int l)
{
while (str[l-1-len[x]]!=str[l])
x=fail[x];
return x;
}
int insert(int x)
{
int c=str[x]-'a';
int p=getfail(suf,x);
if (!next[p][c])
{
int q=newnode();
len[q]=len[p]+2;
fail[q]=next[getfail(fail[p],x)][c];
next[p][c]=q;
}
p=next[p][c];
cnt[p]++;
suf=p;
return suf;
}
void calc()
{
for (int i=tot-1;i>=0;i--)
{
ans=max(ans,1ll*cnt[i]*len[i]);
cnt[fail[i]]+=cnt[i];
}
}
}t;
int main()
{
freopen("palindrome.in","r",stdin);
freopen("palindrome.out","w",stdout);
scanf("%s",str);
n=strlen(str);
t.init();
for (int i=0;i<n;i++)
t.insert(i);
t.calc();
printf("%lld\n",ans);
fclose(stdin);
fclose(stdout);
}
复杂度
首先有一条定理
长度为n的字符串本质不同的回文子串数目最多为n。
证明有很多,可以通过
Manacher
算法过程证明,也可以分析字符串性质,在这里不再讨论,参考资料的最后一项讲了。
然后空间复杂度显然为
O(n|Σ|)
(
Σ
为字符集)或
O(n)
,取决于你怎么存树。
时间复杂度我是这样分析的,我们考虑后缀链的长度,显然最多为
n
,每次插入的过程就相当于给后缀链长度减去若干之后加上
参考资料
国外博客:http://adilet.org/blog/25-09-14/
Codeforces上的介绍:http://codeforces.com/blog/entry/13959
一个不懒的人(然而他配的图也是copy原论文的)的博客:http://blog.csdn.net/u013368721/article/details/42100363
PDF的论文(不是原论文,作者Victor Wonder,写的很详细,UOJ上有链接):PalindromicTree.pdf