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 algorithm,具体看这里http://leetcode.com/2011/11/longest-palindromic-substring-part-ii.html
或者有比较好的博客:http://blog.csdn.net/ggggiqnypgjg/article/details/6645824
编码步骤如下:
1)在s字符串字符间添加特殊字符,使得原s字符串无论是奇数长度还是偶数长度,都变为奇数长度处理,变化后的字符串记为sNew;
2)用数组P[id]记录以字符sNew[id]为中心的最长回文串的半长度;
前两步如下所示:
s : w a a b w
sNew: $ # w # a # a # b # w #
P[id] : 1 1 2 1 2 3 2 1 2 1 2 1
3) 在O(n)时间求出数组P,然后遍历一遍P,可以由sNew中恢复出最长回文串。
用 O(n)时间求出数组P的方法,见代码,里面有详细注释。
class Solution { public: string longestPalindrome(string s) { string result; string sNew(1,'$'); sNew.push_back('#'); int len = s.size(); if(len==0) return result; else if(len==1) return s; for(int i=0;i<len;i++){ sNew.push_back(s[i]); sNew.push_back('#'); }//end for int lenNew = 2*(len+1); vector<int> P(lenNew,1); Pk(P,lenNew,sNew); vector<int> P0(P); sort(P0.begin(),P0.end()); int maxlen = P0[lenNew-1]; int index; for( index=0;index<lenNew;index++){ if(P[index]==maxlen) break; } if(sNew[index]!='#'){ result.push_back(sNew[index]); maxlen -= 2; index += 2; }else{ maxlen -= 1; index += 1; } while(maxlen>0){ result.insert(result.begin(),sNew[index]); result.push_back(sNew[index]); index += 2; maxlen -= 2; } return result; } private: void Pk(vector<int> &P,int n,string s){ int i,mx=0,id;//id是对称中心点的下标,mx是对称段的上届 for(i=1;i<n;i++){ if(mx > i) P[i] = min(P[2*id-i],mx-i);//j=2*id-i,j是i关于id的对称点(和底下的while语句合起来,使得P[i]不用多重复计算) else P[i]=1; while(s[i+P[i]]==s[i-P[i]])//计算以i点为中心的最大回文段,将最大回文长度的一半大小记录在P[i]中 P[i]++; if(P[i]+i>mx){ mx=P[i]+i;//更新当前点的对称段上届mx id = i;//更新当前对称中心点的下标id } }//end for }//end func };