Manacher算法求解回文字符串
Manacher算法可以在\(O(N)\)时间内求解出一个字符串的所有回文子串(正反遍历相同的字串)。
注:回文串显然有两种,一种是奇数长度,如abczcba,有一个中心字符z;另外一种是偶数个长度,如abccba,没有中心字符,下面提到暂时都是只查找奇数长度的字符串
要理解Manacher算法,首先假象一个随机生成的字符串,枚举每个字符作为中心,向两边不断拓展,判断是否相等,直到两边不相等或者走到边界为止,就可以得到每个字符为中心的最大回文长度了(记作\(f_i\)),显然第\(i\)个字符加上左右\(f_i\)的字符就可以构成\(i\)为中心的最长回文串\(S_{[i-f_i+1, i+f_i-1]}\),而\(i\)为中心的更短的字串,显然也是回文串了,这样就求出了所有回文串。
void BF(char *s, int len, int *f) {
for (int i = 1; i <= len; i++) {
f[i] = 1;
while (s[i+f[i]] == s[i-f[i]]) ++f[i];
}
}
但是如果字符大量重叠(如abababab...),几乎每次拓展都会拓展到最边界,效率就会达到平方级。解决这个问题,就应该想到利用回文串的性质,利用已经得到的\(f_i\)来推出当前的\(f_i\)。
那么回文串有什么性质?首先是对称下标构成的字串肯定对称(比如abczcba,\(S_{[1, 3]}=S_{[7, 4]}\)),而且回文串的对称串依然是自己(定义)。所以,一个回文串中如果有另一个回文串,那么子串的对称下标肯定也构成了一个相同的回文串,可以直接推出来。换言之,如果我们知道一个回文串内左半边的对称串,就可以直接得到他右半边的对称串

所以我们记录下达到过的最靠右的点和他的中心点(记为\(maxR\)和\(mid\),当然你也可以只记录\(mid\),用\(mid+f[mid]\)表示右边界)。只要枚举的\(i\)还在右边界以内,就尝试用\(f[mid*2-i]\)来更新\(f[i]\)。当然如果左半边回文串的最长左边界\(i-f[i]+1\)已经不在\(mid\)的回文范围内了,那就顶到最左边,把\(f[i]\)更新为\(f[mid]+mid-i\)(也就是最右边\(maxR\)处)。这时就需要继续往后更新,将\(maxR\)往右拓展。

这里是一份参考代码,这里\(maxR\)是开区间。和上面的暴力一样没有做边界特判,应该将\(S[0]和S[len+1]\)设为两个原字符串中没有且不相等的字符(否则可能加上两端,多一个回文串,然后再往外走导致越界)。显然\(f[i]\)取\(f[mid]+mid-i\)时才会执行之后的更新。
void Manacher(char *s, int len, int *f) {
static int maxR, mid;
for (int i = 1; i <= len; i++) {
f[i] = (i < maxR) ? min(f[mid*2-i], f[mid]+mid-i) : 1;
while (s[i+f[i]] == s[i-f[i]]) ++f[i];
if (i + f[i] > maxR)
maxR = (mid = i) + f[i];
}
}
那么为什么只需要这一个优化就可以做到线性呢?因为这样已经可以做到每个字符只被访问一次(算上和后面的字符比较相等就是两次)。回看第一张图,\(maxR\)左侧是已经访问过的,右侧是没有访问过的。这些已经访问过但\(i\)还没有遍历到的位置都可以\(O(1)\)求解,而\(maxR\)只会不断向右移动,因此一定是\(O(N)\)的。其本质就是利用回文串的性质避免了\(mid\)到\(maxR\)处的所有计算,只在往后更新的时候计算。
最后谈谈偶数长度回文串,偶数长度串的“中心”相当于于是字符之间的空隙。处理它们的一种方法是在每两个字符串之间加入不存在于原字符串的字符(如#),然后在执行算法,此时以#为中心的回文串就是偶数回文串。或者先做奇数长度,然后找到所有满足\(S[i]==S[i+1]\)的下标,将他们看作“一个中心“后进行拓展。
for (int i = 1; i <= len; i++)
s0[(i << 1) - 1] = s[i], s0[i << 1] = '#';
Manacher算法求解回文字符串的更多相关文章
- Codeforces Global Round 7 D2. Prefix-Suffix Palindrome (Hard version)(Manacher算法+输出回文字符串)
This is the hard version of the problem. The difference is the constraint on the sum of lengths of s ...
- SPOJ STC02 - Antisymmetry(Manacher算法求回文串数)
http://www.spoj.com/problems/STC02/en/ 题意:给出一个长度为n的字符串,问其中有多少个子串s可以使得s = s按位取反+翻转. 例如样例:11001011. 10 ...
- hdu5340—Three Palindromes—(Manacher算法)——回文子串
Three Palindromes Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others ...
- HDU 5371(2015多校7)-Hotaru's problem(Manacher算法求回文串)
题目地址:HDU 5371 题意:给你一个具有n个元素的整数序列,问你是否存在这样一个子序列.该子序列分为三部分,第一部分与第三部分同样,第一部分与第二部分对称.假设存在求最长的符合这样的条件的序列. ...
- Manacher算法求回文半径
http://wenku.baidu.com/link?url=WFI8QEEfzxng9jGCmWHoKn0JBuHNfhZ-tKTDMux34CeY8UNUwLVPeY5HA3TyoKU2XegX ...
- Manacher算法:求解最长回文字符串,时间复杂度为O(N)
原文转载自:http://blog.csdn.net/yzl_rex/article/details/7908259 回文串定义:"回文串"是一个正读和反读都一样的字符串,比如&q ...
- 最长回文字符串(manacher算法)
偶然看见了人家的博客发现这么一个问题,研究了一下午, 才发现其中的奥妙.Stupid. 题目描述: 回文串就是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串. ...
- 第5题 查找字符串中的最长回文字符串---Manacher算法
转载:https://www.felix021.com/blog/read.php?2040 首先用一个非常巧妙的方式,将所有可能的奇数/偶数长度的回文子串都转换成了奇数长度:在每个字符的两边都插入一 ...
- hdu3068 求一个字符串中最长回文字符串的长度 Manacher算法
最长回文 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
随机推荐
- lvm 扩容
总体思路: 逻辑卷要扩容,先扩容对应卷组, 扩容卷组的方式: 添加新的物理卷(磁盘已有分区,扩容后新建分区:或者新加了一块硬盘创建了新的物理卷),vgextend myvg /dev/vdb 扩容,/ ...
- 在JSP页面里,时间控件的JS位置在下面然后就显示不出来
在JSP页面里,时间空间的JS位置在下面然后就显示不出来,放到前面然后就显示出来了, 情何以堪啊,开始还以为是什么错误.
- JAVA读取本地html文件里的html文本
/** * 读取本地html文件里的html代码 * @param file File file=new File("文件的绝对路径") * @return */ public s ...
- JAVA使用aspose实现word文档转pdf文件
引入jar包 下载地址:https://yvioo.lanzous.com/iezpdno3mob 然后打开下载的目录打开cmd执行 mvn install:install-file -Dfile=a ...
- 深入理解Akka Actor模型
Carl Hewitt 在1973年对Actor模型进行了如下定义:"Actor模型是一个把'Actor'作为并发计算的通用原语". Actor是异步驱动,可以并行和分布式部署及运 ...
- istio的sidecar原理学习
目的 从内嵌到应用的SDK模式转成istio servicemesh,再到最新提出来的proxyless可谓是发展太快了.刚开始我只是围绕着服务注册和发现是怎么转变来展开研究,但是发现这个话题有点大, ...
- 【LeetCode】362. Design Hit Counter 解题报告 (C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 字典 日期 题目地址:https://leetcode ...
- 【LeetCode】812. Largest Triangle Area 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 三重循环 组合函数 日期 题目地址:https:// ...
- The Monkey King(hdu5201)
The Monkey King Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)T ...
- Cornfields(poj2019)
Cornfields Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 6798 Accepted: 3315 Descri ...