回文树(Palindrome Tree)/回文自动机(Palindrome Automaton)学习小记
来源:互联网 发布:seo常用的工具 编辑:程序博客网 时间:2024/05/18 07:22
简介
回文树(回文自动机),是解决一类回文串问题的强大数据结构,比
这个数据结构比较新,由来自战斗民族的神犇MikhailRubinchik在2014年的Petrozavodsk夏令营提出。
这个数据结构代码量其实超级少。
必备技能
最好会至少一种自动机
分析
回文树严格来讲是由两棵树构成的森林,再加上一堆后缀链(失配链)。其中一棵树代表长度为奇数的回文串,另一棵树代表长度为偶数的回文串。树上每个节点都代表一种与其它节点不同的回文串,所以每个点上都有诸如长度
后缀链
初始时,偶数树的根节点代表一个空串,长度为
插入操作过程中,我们需要记录当前插入的串的最长回文后缀
我们找到
由于blog主特别懒,这里就不配图了,大家结合代码理解理解吧。
建完树,我们要重算一次每个回文串出现次数。过程很简单,就是倒序枚举节点,假设枚举到
然后剩下的就是结合题目乱搞了。
代码实现
注:以下代码对应题目[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。
证明有很多,可以通过
然后空间复杂度显然为
时间复杂度我是这样分析的,我们考虑后缀链的长度,显然最多为
参考资料
国外博客: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
- 回文树(Palindrome Tree)/回文自动机(Palindrome Automaton)学习小记
- 回文树/回文自动机 Palindromic Tree 学习小记
- 回文树(回文自动机)学习小记
- 回文自动机学习小记
- Palindrome回文
- Palindrome 回文
- WOJ 1583 Palindrome(回文自动机)
- 【WHU1583】Palindrome-回文自动机+双向插入
- WHU 1583 Palindrome(回文树)
- 回文palindrome(Java版)
- palindrome(回文)判断方法
- Valid Palindrome 回文
- palindrome (回文词)
- leetcode 回文系列 Palindrome
- 回文判定 Valid Palindrome
- 【字符串回文】Valid Palindrome
- Palindrome Number --回文整数
- Palindrome<回文>字符串问题
- 用provider获取手机联系人信息
- 使用eclipse的Hibernate插件创建session完成对数据库的记录追加
- EFI基本概念之PPI
- php Session存储到Redis的方法
- FFmpeg在iOS上完美编译
- 回文树(Palindrome Tree)/回文自动机(Palindrome Automaton)学习小记
- 重构——注册——存储过程+事务
- JavaScript快速入门(三)
- dede企业会员调用的sql函数
- JavaScript快速入门(四)
- LeetCode Algorithms #217 <Contains Duplicate>
- git fetch 与git pull 区别
- JavaScript第一课——使用JavaScript
- python 时间方法