[LeetCode] Longest Palindromic Substring(manacher algorithm)

时间:2023-03-08 18:48:31
[LeetCode]  Longest Palindromic Substring(manacher algorithm)

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(,'$');
sNew.push_back('#');
int len = s.size();
if(len==)
return result;
else if(len==)
return s;
for(int i=;i<len;i++){
sNew.push_back(s[i]);
sNew.push_back('#');
}//end for int lenNew = *(len+);
vector<int> P(lenNew,);
Pk(P,lenNew,sNew);
vector<int> P0(P);
sort(P0.begin(),P0.end());
int maxlen = P0[lenNew-];
int index;
for( index=;index<lenNew;index++){
if(P[index]==maxlen)
break;
}
if(sNew[index]!='#'){
result.push_back(sNew[index]);
maxlen -= ;
index += ;
}else{
maxlen -= ;
index += ; }
while(maxlen>){
result.insert(result.begin(),sNew[index]);
result.push_back(sNew[index]);
index += ;
maxlen -= ;
}
return result;
}
private:
void Pk(vector<int> &P,int n,string s){
int i,mx=,id;//id是对称中心点的下标,mx是对称段的上届
for(i=;i<n;i++){
if(mx > i)
P[i] = min(P[*id-i],mx-i);//j=2*id-i,j是i关于id的对称点(和底下的while语句合起来,使得P[i]不用多重复计算)
else
P[i]=; 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
};