DP专题

5. Longest Palindromic Substring 最长回文子串

题意:找到字符串的最长回文子串(子串是连续的,子序列是可以间断的)

我的解法:将每两个字符中间插入一个‘#’,这个就可以一起判断奇数回文串和偶数回文串,分别将每个字符作为中心往两侧最长回文,更新结果。时间复杂度O(n^2)

我的代码:

class Solution {
public:
    string longestPalindrome(string s) {
        string ss, ret;
        for (int i = 0; i < s.size(); i++) {
            ss += '#';
            ss += s[i];
        }
        ss += '#';
        int ans = 0, n = ss.size();
        for (int i = 0; i < n; i++) {
            int j = 1;
            while (i+j < n && i-j >= 0 && ss[i+j] == ss[i-j]) j++;
            if (ss[i] == '#') {
                if (j > ans) {
                    ans = j;
                    ret = ss.substr(i-j+1, 2*j-1);
                }
            }
            else {
                if (j-1 >= ans) {
                    ans = j-1;
                    ret = ss.substr(i-j+1, 2*j-1);
                }
            }
        }
        string gg;
        for (int i = 0; i < ret.size(); i++)
            if (ret[i] != '#') gg += ret[i];
        return gg;
    } 
};
View Code

最优解:Manacher算法,时间、空间复杂度O(n)

Manacher算法:https://segmentfault.com/a/1190000003914228

代码:

class Solution {
public:
    string longestPalindrome(string s) {
        string ss = "#", tmp, ret;
        for (int i = 0; i < s.size(); i++) ss = ss+s[i]+'#'; 
        int n = ss.size(), MaxRight = 0, pos = 0;
        vector<int> RL(n, 0);
        for (int i = 0; i < n; i++) {
            if (i < MaxRight) RL[i] = min(RL[2*pos-i], MaxRight-i);
            else RL[i] = 1;
            while (i-RL[i] >= 0 && i+RL[i] < n && ss[i-RL[i]] == ss[i+RL[i]]) RL[i]++;
            if (i+RL[i]-1 > MaxRight) {
                MaxRight = i+RL[i]-1;
                pos = i;
            }
            if (2*RL[i]-1 > tmp.size()) tmp = ss.substr(i-RL[i]+1, 2*RL[i]-1);
        }
        for (int i = 0; i < tmp.size(); i++)
            if (tmp[i] != '#') ret += tmp[i];
        return ret;
    } 
};
View Code

 

posted @ 2018-03-23 14:45  Silence、  阅读(126)  评论(0编辑  收藏  举报