LeetCode-Longest Palindromic Substring-最长回文子串-Manacher

https://oj.leetcode.com/problems/longest-palindromic-substring/

这道题O(n^2)的DP的解法会超时。大致思路就是从0-n计算子串的最大子串,并利用ispar[p][q]数组记录[p,q]是否是回文以避免每次判断子串是否是回文。

class Solution {
public:
    int n,m;
    string longestPalindrome(string s) {
        n=s.length();
        vector<vector<bool>> ispar(n+1,vector<bool>(n+1,false));
        for(int i=0;i<n;i++) {ispar[i][i]=true;ispar[i][i+1]=true;}
        int start=0;
        int len=1;
        for(int i=0;i<n;i++){
            for(int j=i-1;j>=0;j--){
                if(s[j]==s[i]) {
                    ispar[j][i]=ispar[j+1][i-1];
                    if(ispar[j][i] && i-j+1>len){
                        len=i-j+1;
                        start=j;    
                    }
                }
            }
        }
        string res=s.substr(start,len);
        return res;
    }
};

搜了答案看到了O(n)Manacher算法,这个方法有两个技巧:

1,通过添加特殊字符避免判断偶数长度回文,将所有回文都转换为奇数长度。

2,利用以前判断过的最长回文与当前字符i为中心的回文的位置关系为当前回文排除掉一些较短的可能。

class Solution {
public:
    int n,m;
    string longestPalindrome(string s) {
        n=s.length();
        string ss;
        for(int i=0;i<n;i++){
            ss+="#";
            ss+=s[i];
        }
        ss+="#";
        m=ss.length();
        vector <int> p(m,0);
        int mx=0;
        int id=0;
        for(int i=1;i<m;i++){
            if (mx>i) p[i]=min(p[2*id-i],mx-i);
            for(int j=p[i]+1;i+j<m && i-j>=0;j++){
                if (ss[i-j]==ss[i+j]) p[i]++;
                else break;
            }
            if (i+p[i]>mx){
                id=i;
                mx=i+p[i];
            }
        }
        int maxp=0;
        for (int i=0;i<m;i++) {
            if(p[i]>maxp) {
                id=i;
                maxp=p[i];
            }
        }
        string res;
        for(int i=id-maxp;i<=id+maxp;i++){
            if(ss[i]!='#') res+=ss[i];
        }
        return res;
    }
};

 

posted @ 2014-10-17 16:46  zombies  阅读(144)  评论(0编辑  收藏  举报