求最长回文子串:Manacher算法
主要学习自:http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-ii.html
问题描述:回文字符串就是左右对称的字符串,如:"abba",而最长回文子串则是字符串长度最长的回文子字符串,如"abbaca"的最长回文子串为"abba"。
常规解法:显而易见采用嵌套循环的方式可以“暴力”结算出答案,其时间复杂度为O(n^2),而Manacher算法是一种更加省时的算法,其时间复杂度为O(n).
主要思路:
首先使用#(或其他什么符号)填充字符串,并声明一个数组来记录以字符串的每一个字符作为中心,回文字符的半径,使之成为这个样子:
str = # a # b # a # c # a # c # a # b # c # a # c #
arr = 0 1 0 3 0 1 0 3 0 7 0 3 0 1 0 1 0 1 0 3 0 1 0
由此我们可以看出,添加#的作用在于使得字符串无论是奇数长度还是偶数长度,在经过处理后都可以统计以每个字符为中心的回文半径,而偶数长度的回文无法统计这个,如:“abba”
计算出arr后,很容易得到最大回文子串的长度为7,为"bacacab"。
所以这个算法的关键在于计算arr,通过观察我们发现,arr中的数值其实也是对称的:

比如上述例子,以T[11]作为对称中心(回文半径为9),要求T[13]处的回文半径时,可根据其相对于T[11]的对称T[9]来计算,显然arr[13]=arr[9]。可以根据这个例子计算arr[i]=arr[i'].
但是这一方法并不是总是适用的,如:

当i=15时,由于arr[i']>R-i,所以arr[15]不一定等于与之对称的arr[7],如本例中arr[15]=5.因此我们得到以下规律:
if arr[ i’ ] ≤ R – i,
then arr[ i ] ← arr[ i’ ]
else P[ i ] ≥ R – i.
知道了如何计算回文半径,如何确定回文中心呢(即图中的C)?
采用的方式为i+arr[i]>R,则将C替换为i ,R替换为i+arr[i]
直接贴代码:
string preProcess(string str)
{
//$是开头标识,string的结尾标识为\0
string encoded = "$";
int strlen = str.length();
//加#的目的在于使得偶数位的回文字串更加容易辨别,如:"1221",在计算回文长度数组时,不好计算,但$1#2#2#1\0的回文长度(半径)数组为[0,0,0,1,3,1,0,0,0]
for (int i = ; i < strlen; i++)
{
encoded += "#" + str.substr(i,);
}
encoded += "#";
return encoded;
} string longestPalindrome(string str)
{
string temp = preProcess(str);
//回文子串的中心
int palindrome_center = ;
//回文子串的右边界
int right_border = ;
int strlen = temp.length();
//用来存储以该点为中心的回文字符串的半径长度,注意这里是半径长度,因为字符串是经过处理的,包含了#
int * plength_array = new int[strlen];
//i相对于center的对称处
int mirror_i = ;
//循环从1开始因为开头为标示符“$”
for (int i = ; i < strlen; i++)
{
//i相对于回文中心的对称处
mirror_i = * palindrome_center - i;
if (mirror_i>&& right_border > i)//i在回文字符子串内
{
//若范围没有超过右边界,则回文数对称
if (right_border - i > plength_array[mirror_i])
plength_array[i] = plength_array[mirror_i];
else
plength_array[i] = right_border - i;//*先取一个最小值
}
else
plength_array[i] = ;
//针对上面*处先取一个最小值的情况
while (temp[i + + plength_array[i]] == temp[i - - plength_array[i]])
plength_array[i]++;
//如果回文字串的长度超过了现有的右边界,则确立新的中心和右边界
if (i + plength_array[i] > right_border)
{
palindrome_center = i;
right_border = i + plength_array[i];
}
}
//寻找plength_array中的最大元素
int maxlen = ;
//最长回文的中心
int maxlen_center = ;
for (int j = ; j < strlen; j++)
{
if (plength_array[j]>maxlen)
{
maxlen = plength_array[j];
maxlen_center = j;
}
}
delete[] plength_array;
return str.substr((maxlen_center--maxlen)/,maxlen);
}
求最长回文子串:Manacher算法的更多相关文章
- 求最长回文子串——Manacher算法
回文串包括奇数长的和偶数长的,一般求的时候都要分情况讨论,这个算法做了个简单的处理把奇偶情况统一了.算法的基本思路是这样的,把原串每个字符中间用一个串中没出现过的字符分隔开来(统一奇偶),用一个数组p ...
- 九度OJ 1528 最长回文子串 -- Manacher算法
题目地址:http://ac.jobdu.com/problem.php?pid=1528 题目描述: 回文串就是一个正读和反读都一样的字符串,比如"level"或者"n ...
- lintcode最长回文子串(Manacher算法)
题目来自lintcode, 链接:http://www.lintcode.com/zh-cn/problem/longest-palindromic-substring/ 最长回文子串 给出一个字符串 ...
- 最长回文子串—Manacher 算法 及 python实现
最长回文子串问题:给定一个字符串,求它的最长回文子串长度.如果一个字符串正着读和反着读是一样的,那它就是回文串. 给定一个字符串,求它最长的回文子串长度,例如输入字符串'35534321',它的最 ...
- 51nod1089 最长回文子串 manacher算法
0. 问题定义 最长回文子串问题:给定一个字符串,求它的最长回文子串长度. 如果一个字符串正着读和反着读是一样的,那它就是回文串.下面是一些回文串的实例: 12321 a aba abba aaaa ...
- hihocoder #1032 : 最长回文子串 Manacher算法
题目链接: https://hihocoder.com/problemset/problem/1032?sid=868170 最长回文子串 时间限制:1000ms内存限制:64MB 问题描述 小Hi和 ...
- 5. Longest Palindromic Substring(最长回文子串 manacher 算法/ DP动态规划)
Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...
- HiHo 1032 最长回文子串 (Manacher算法求解)
/** * 求解最长回文字串,Manacher算法o(n)求解最长回文子串问题 **/ #include<cstdio> #include<cstdlib> #include& ...
- hihoCoder #1032 : 最长回文子串 [ Manacher算法--O(n)回文子串算法 ]
传送门 #1032 : 最长回文子串 时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相 ...
- 最长回文子串Manacher算法模板
Manacher算法能够在O(N)的时间复杂度内得到一个字符串以任意位置为中心的回文子串.其算法的基本原理就是利用已知回文串的左半部分来推导右半部分. 首先,在字符串s中,用rad[i]表示第i个字符 ...
随机推荐
- LEfSe分析
LEfSe软件用于发现两组或两组以上的biomarker,主要是通过非参数因子Kruskal-Wallis秩和检验来实现的.运行LEfSe软件主要分三大步骤:第一步:需要把普通的物种.基因等等的丰度信 ...
- Nginx基础知识之————RTMP模块中的中HLS专题(翻译文档)
一.在Nginx配置文件的RTMP模块中配置hls hls_key_path /tmp/hlskeys; 提示错误信息: nginx: [emerg] the same path name " ...
- appium 等待方法 转
前些日子,配置好了appium测试环境,至于环境怎么搭建,参考:http://www.cnblogs.com/tobecrazy/p/4562199.html 知乎Android客户端登陆:htt ...
- 准循环LDPC码用于公钥密码时的奇偶校验矩阵
设H为奇偶校验矩阵,其行权重为d.Q为转置矩阵,其行权重为m.对于LDPC码,有d/n<< 1, m/n< 1. H´=H·QT是用于公钥密码的奇偶校验矩阵.它不是老密码G的奇偶校验 ...
- phalcon: 当删除循环删除一组数据,需要判断影响的行affectedRows
phalcon:有一个表,按日期查找半年以为的数据,由于数据量特别大,不能一次:delete删除数据,否则会造成数据表卡顿,数据库锁死. 那么只能循环的删除数据,每次删除100条左右,知道删除为止., ...
- 在ie7中overflow:hidden失效问题及解决方案
css兼容ie7: 做页面的时候用负边距居中的时候在IE7下面,父节点中的overflow:hiden失效的问题,查阅了一些资料,总结一下解决方法. 问题原因: 当父元素的直接子元素或者下级子元素的样 ...
- 磁盘文件系统Fat、Fat32、NTFS、exFAT的优缺点
我们在Windows系统里格式化磁盘的时候,文件系统的选项里可以看到有“FAT”.“FAT32”.“NTFS”等选项,在对U盘或其他移动存储设备 格式化的时候还会出现“exFAT”选项,那么这四种磁盘 ...
- yii2-basic后台管理功能开发之三:自定义GridView列显示
在第二篇 yii2-basic后台管理功能开发之二:创建CRUD增删改查 中,我们利用gii工具生成的结果一般并不是我们想要的结果. 我们需要根据自己的需求自定义列显示.我遇到的主要是一下变更: 时间 ...
- C#面向对象特征的具体实现及作用详解
转自:http://www.jb51.net/article/42390.htm 众所周知,面向对象编程的特点为:封装.继承.多态.C#是一门完全面向对象的语言,由于比Java推出的时间还要晚,所以对 ...
- OpenBSD内核之引导MBR
MBR的介绍网上很多,没错,就那个最后以0x55AA结尾的512字节的引导块,OpenBSD提供了引导MBR实现:OpenBSD在x86上的引导过程为MBR --> PBR --> boo ...