最近无意中看到了这个数据结构,顺便也就学习了一下。
而且发现网上关于这个算法的描述有很多地方是错的,在这里做了一些更正。
处理字符串的算法很多:KMP,E-KMP,AC自动机,后缀三兄弟:后缀树、后缀数组、后缀自动机,Trie树、Trie图,符串hash...
但以上数据结构在处理回文串上还是稍有欠缺,用这些来处理回文显得太小题大做。
于是有了Manacher算法,代码短、容易理解、时间O(n)、无需考虑奇偶回文情况,很完美的算法!
当然这篇博客的重点不在Manacher算法,有关Manacher算法请点击这里!
Manacher算法可以在O(n)时间内处理出S串每个位置的最长回文串,但如果要统计S串中有多少回文串,
或者S串的所有子串的回文串的个数,那么就要用到一种和Manacher一样优雅的数据结构:回文自动机。
一.What Is Palindromic auto-machine?
回文自动机,又叫回文树,是由俄罗斯人 MikhailRubinchik于2014年夏发明的(http://codeforces.com/blog/entry/13959).
这是一种比较新的数据结构,在原文中已有详细介绍与代码实现。
回文树其实不是严格的树形结构,因为它有是两棵树,分别是偶数长度的回文树和奇数长度的回文树,树中每个节点代表一个回文串。
为了方便,第一棵树的根是一个长度为0的串,第二棵就是为-1的串,不要感到奇怪,就是-1。
可以证明,最多只有n个结点(n是串的长度)。这个可以用Manacher算法来证明。
如果某结点代表的是串ccabacc,那么它的父亲代表的串就是去掉前后两个字符cabac。
每个点还有一个fail指针,表示这个串的后缀中最长的回文串,比如babab的fail指向bab,bab的指向b。
方法的思想和KMP,AC自动机很类似,如果你理解了KMP与AC自动机,那么这个算法基本可以一看就懂。
二.How To Build Palindromic auto-machine?
注:以下部分图片来自互联网
假设现在我们有串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(字符集大小)),这个时间复杂度比较神奇。如果空间需求太大,可以改成邻接表的形式存储,不过相应的要牺牲一些时间。
三.The Use Of Palindromic auto-machine
1.求串S前缀0~i内本质不同回文串的个数(两个串长度不同或者长度相同且至少有一个字符不同便是本质不同)
2.求串S内每一个本质不同回文串出现的次数
3.求串S内回文串的个数(其实就是1和2结合起来)
4.求以下标i结尾的回文串的个数
四.some problem
1.2014-2015 ACM-ICPC, Asia Xian Regional Contest G The Problem to Slow Down You
2.ural1960. Palindromes and Super Abilities
3.WHU1583 Palindrome
4.Подпалиндромы
五.Template code
转载请注明:http://www.cnblogs.com/crazyacking/p/5234823.html