您的位置:首页 > 其它

最长回文子串 Longest Palindromic Substring

2015-04-19 11:17 225 查看
思路:

方法一:暴力,时间复杂度O(n^3),空间复杂度O(1)

不断判断子串是否回文。

//Longest Palindromic Substring
string longestPalindrome(string s) {
    int length=s.size();
    int maxLength=1;
    int start=0;
    for(int i=0;i<length;i++) {
        for(int j=i+1;j<length;j++) {
            int tmp1,tmp2;
            for(tmp1=i,tmp2=j;tmp1<tmp2;tmp1++,tmp2--) {
                if(s.at(tmp1)!=s.at(tmp2)) break;
            }
            if(tmp1>=tmp2 && j-i+1 >maxLength) {
                maxLength = j-i+1;
                start=i;
            }
        }
    }
    if(maxLength>0) {
        return s.substr(start,maxLength);
    }
    return NULL;
}


方法二:DP,时间复杂度O(n^2),空间复杂度,O(n^2)

p[i][j]表示以i开始j结束的子串是否满足回文:

p[i][j]==1 是回文子串;

p[i][j]!=1 不是回文子串;

状态转移方程:

p[i][i]=1;

p[i][i+1]=1 : if s[i]==s[i+1]

p[i][j]=1 : if s[i]==s[j] && p[i+1][j-1]=1

class Solution {
public:
    string longestPalindrome(string s) {
        int n = s.length();
        int longestBegin = 0;
        int maxLen = 1;
        bool table[1000][1000] = {false};
        for(int i=0;i<n;i++) {
            table[i][i] = 1;
        }
        for(int i=0;i<n-1;i++) {
            if(s[i] == s[i+1]) {
                table[i][i+1]=1;
                maxLen=2;
                longestBegin=i;
            }
        }
        for(int len=3;len<=n;len++) {
            for(int i=0;i<n-len+1;i++) {
                int j=i+len-1;
                if(s[i]==s[j] && table[i+1][j-1]==1) {
                    table[i][j]=1;
                    maxLen=len;
                    longestBegin=i;
                }
            }
        }
        return s.substr(longestBegin,maxLen);
    }
};


方法三:中心扩展法

设字符串s长度为n

对于长度为奇数的回文子串,沿着中心字符轴对称,可能的中心点共有n个;

对于长度为偶数的回文子串,沿着中心空字符轴对称,可能的中心点共有n-1个;

所以我们可以一个一个中心点的去试探,判断以此为中心的子串是否是回文子串。

class Solution {
public:
    string longestPalindrome(string s) {
        const int length=s.size();
        if(length == 0) return "";
        int maxLength=1;
        int start=0;
     
        for(int i=0;i<length;i++) {
            int j=i-1,k=i+1;
            while(j>=0 && k<length && s[j]==s[k]) {
                if(k-j+1 > maxLength) {
                    maxLength=k-j+1;
                    start=j;
                }
                j--;
                k++;
            }
        }
        for(int i=0;i<length;i++) {
            int j=i,k=i+1;
            while(j>=0 && k<length && s[j]==s[k]) {
                if(k-j+1 > maxLength) {
                    maxLength=k-j+1;
                    start=j;
                }
                j--;
                k++;
            }
        }
        return s.substr(start,maxLength);
    }
};


方法四:Manacher‘s Algorithm

这个算法的时间复杂度在O(n),空间复杂度也为O(n),学习完这个算法觉得设计的太巧妙了!充分利用了回文串的对称性。

看了好几篇介绍的博文,这篇写的最易理解:《Manacher's algorithm:优雅的求最长回文子串》

class Solution {
public:
    string preProcess(string s) {
        int n=s.length();
        if(n==0) return "^$";
        string ret="^";
        for(int i=0;i<n;i++) {
            ret += "#"+s.substr(i,1);
        }
        ret += "#$";
        return ret;
    }

    string longestPalindrome(string s) {
        string T = preProcess(s);
        const int n = T.length();
        int P
;
        int center = 0, mx = 0;
        for(int i=1;i<n-1;i++) {    //i从第一个“#”循环到到最后一个“#”
            int i_mirror = 2*centor-i;
            //P[i] = (mx > i) ? min(P[i_mirror], mx - i) : 0;
            if(mx > i) {
                if(i+P[i_mirror] < mx) {
                    P[i] = P[i_mirror];
                }else {
                    P[i] = mx - i;
                }
            }else {
                P[i] = 0;
            }
            
            //calculate P[i] at i
            while(T[i + 1 + P[i]] == T[i - 1 - P[i]]) {
                P[i]++;
            }
            //update center and mx
            if(i + P[i] > mx) {
                center = i;
                mx = i + P[i];
            }
        }
        //find the maximum element in P
        int max_len = 0;
        int centor_index = 0;
        for(int i=1; i<n-1; i++) {
            if(P[i]>max_len) {
                max_len = P[i];
                centor_index = i;
            }
        }
        return s.substr((centor_index - 1 - max_len)/2, max_len);
    }
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: