[C++] LeetCode 5. 最长回文子串

题目

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba"也是一个有效答案。

示例 2:
输入:"cbbd"
输出: "bb"

思路解析

这题求最长回文子串,有三种方法可以采用,最简单的是用动态规划,时间复杂度是O( n2 n 2 ),另外一种是中心扩展,第三种方法是称为马拉车的算法。

方法一 动态规划

动态规划需要开一个二维数组,DP[i][j]=s[i]==s[j]&&DP[i+1][j-1],时间复杂度较高
代码:

class Solution {
public:
    string longestPalindrome(string s) {
        int len=s.size();
        vector<vector<int>> flag(len,vector<int>(len,0));
        int maxres=0,idx=0;
        for(int i=0;ifor(int j=0,k=i;jif(k==j) flag[j][k]=1;
                else if(s[k]==s[j]&&j+1==k) flag[j][k]=2;
                else if(s[k]==s[j]&&flag[j+1][k-1]>0) flag[j][k]=flag[j+1][k-1]+2;
                else flag[j][k]=0;
                if(flag[j][k]>maxres){
                    maxres=flag[j][k];
                    idx=j;
                }
            }
        }
        return s.substr(idx,maxres);
    }
};

方法二 中心扩展

这种做法主要是考虑基于一个点为中心,然后左右两边扩展,得出以该点为中心的最长回文串。但是需要注意的是回文串长度是奇数和偶数,有所差别需要都考虑。
时间复杂度高于上一种方法
代码:

//加快代码运行速度
static const auto __ = []() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    return nullptr;
}();

class Solution {
public:
    string longestPalindrome(string s) {
        int n=s.size(),pos=-1,maxlen=0;
        for(int i=0;iint r=1;
            while(i-r>=0&&i+rif(maxlen<2*r-1){
                pos=i-r+1;
                maxlen=2*r-1;
            }
            if(i>=n||s[i]!=s[i+1]) continue;
            r=1;
            while(i-1>=0&&i+1+r1+r]) r++;
            if(maxlen<2*r){
                pos=i-r+1;
                maxlen=2*r;
            }
        }
        return s.substr(pos,maxlen);
    }
};

方法三 马拉车算法

马拉车算法可以实现近似O(n)求解,具体原理见马拉车算法
代码:

//加快代码运行速度
static const auto __ = []() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    return nullptr;
}();
class Solution {
public:
    string longestPalindrome(string s) {
        int ns=s.size(),n=2*ns+1;
        vector<char> str(n,'*');
        vector<int> slen(n,0);
        for(int i=0;i2*i+1]=s[i];
        int curpos=0,curlen=0,maxpos=0,maxr=0;
        for(int i=0;iint mi=2*curpos-i,r=slen[mi];
            if(i+rcontinue;
            }
            r=curpos+curlen-i;
            while(i-r>=0&&i+rif(maxrif(i+maxr>=n) break;
        }
        return s.substr(maxpos/2-maxr/2,maxr);
    }
};

你可能感兴趣的:(Leetdode)