[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(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
};    
原文地址:https://www.cnblogs.com/Xylophone/p/3937700.html