标签:leetcode longest palindromic manacher alogorithm
原题链接:https://leetcode.com/problems/longest-palindromic-substring/
题目:Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.
翻译:求给定字符串中最长回文串的长度
方法:Manacher’s Alogorithm(此算法可达到O(n)时间)
小序:刚开始看这道题大牛的们的解法时,看不懂(原谅我是个渣渣。。。)后来多看了几篇才明白,觉得应该详细记录说明一下
AC代码:
public class Solution { public String longestPalindrome(String s) { int[] p = new int[2048];//用整型数组来保存trans中以res[i]为中心的回文串长度(单边) //将s中各个字符间插入分隔符,以巧妙得忽略s中字符个数的奇偶差异 StringBuilder trans = new StringBuilder("#");//首尾都加额外字符防溢出(实际循环的范围仍是字符串长度,故不影响) for(int i=0; i<s.length(); i++) { trans.append("#"); trans.append(s.charAt(i)); } trans.append("##"); int mx = 0;//保存当前最长回文串的右边界 int id = 0;//保存当前最长回文串的对称中心所在位置 int end_extend = 0;//保存最终确定的最长回文子串的长度 int end_center = 0;//保存最终确定的最长回文子串对称中心在trans中的位置 for(int i=1; i<trans.length()-1; i++) { p[i] = mx>i ? Math.min(p[2*id-i], mx-i) : 1;//其中p[2*id-i]是当前位置i关于id对称位置j=2*id-i的p[j].之所以要取二者中较小值是防止当对应p[j]较大时,以i为中心的p[i]会溢出(超过字符串长度) while(trans.charAt(i+p[i]) == trans.charAt(i-p[i])) //循环检查以i为中心,左右对称位置的值(p[i]为半径的值)是否相同,相同则证明回文串长度有 p[i]++; if(i+p[i] > mx) { //如果当前回文串的右边界已经超过了上个回文串的右边界, mx = i + p[i]; //则更新回文串右边界长度为当前回文串右边界长度 id = i; //同时保存此时的对称中心位置 } if(p[i] > end_extend) { end_extend = p[i]; end_center = i; } } return s.substring((end_center - end_extend)/2, (end_center -end_extend)/2 + end_extend -1); } } <span style="color:#000000;BACKGROUND: rgb(255,255,255)"></span>
<span style="font-size:14px;"><span style="BACKGROUND-COLOR: #ffff33"><span style="color:#000000;BACKGROUND-IMAGE: none; BACKGROUND-ATTACHMENT: scroll; BACKGROUND-REPEAT: repeat; BACKGROUND-POSITION: 0% 0%"></span></span></span>
<span style="font-size:14px;"><span style="BACKGROUND-COLOR: #ffff33"><span style="color:#000000;BACKGROUND-IMAGE: none; BACKGROUND-ATTACHMENT: scroll; BACKGROUND-REPEAT: repeat; BACKGROUND-POSITION: 0% 0%">原理:</span><span style="color:#000000;BACKGROUND-IMAGE: none; BACKGROUND-ATTACHMENT: scroll; BACKGROUND-REPEAT: repeat; BACKGROUND-POSITION: 0% 0%">Manacher</span><span style="color:#000000;BACKGROUND-IMAGE: none; BACKGROUND-ATTACHMENT: scroll; BACKGROUND-REPEAT: repeat; BACKGROUND-POSITION: 0% 0%">’</span><span style="color:#000000;BACKGROUND-IMAGE: none; BACKGROUND-ATTACHMENT: scroll; BACKGROUND-REPEAT: repeat; BACKGROUND-POSITION: 0% 0%">s Alogorithm</span></span></span>
利用一个辅助数组p[i]记录trans[i]为中心的回文子串长度。
(参考自:http://www.cnblogs.com/daoluanxiaozi/p/longest-palindromic-substring.html)
Manacher算法的巧妙之处在于:用mx记录之前保存的最长回文子串长度所能达到的最后边界,用id记录其对称中心,从而计算部分从位置id至位置mx之间元素的p[i]时,利用回文子串的对称性,找其关于id对称位置p[2*id - i],二者相等。如下图:
刚才只提到部分,是因为如果p[2*id-i] > mx-i,假设p[i] = p[2*id - i](即假设以i为中心,可以向其右边扩展p[i]个元素,并且有对应i左边的元素与其对称)显然,这并不总是成立
举例说明:
s :cdabadabac
trans: ##c#d#a#b#a#d#a#b#a#c##
具体如图:
其实正是p[i] =Math.min(p[2*id-i], mx-i) 的原理
欢迎转载学习~
版权声明:本文为博主原创文章,未经博主允许不得转载。
Leetcode:Longest Palindromic Substring之详细分析
标签:leetcode longest palindromic manacher alogorithm
原文地址:http://blog.csdn.net/yangyao_iphone/article/details/46732667