leetCode-5 最长回文子串

425 阅读1分钟

题目描述

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例 1:

输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:

输入: "cbbd"
输出: "bb"

思路1 中心扩散

首先确认一下什么是回文串,aba属于回文串,aa也属于回文串。也就是说回文串分为两种情况,长度为奇数是是以最中间的单个字符开始往两边扩散。长度为偶数时需要以最中间的两个字符开始扩散。因此需要考虑两种扩散方式。

代码如下:

// 从l向左扩散和从r向右扩散,返回此时的最长回文串
string palindrome(string s, int l, int r) {
    while(l >= 0 && r < s.size() && s[l] == s[r]) {
        l--;
        r++;
    }
    return s.substr(l+1, r-l-1);
}

string longestPalindrome(string s) {
    if(s.size() == 0) {
        return "";
    }
    string ans = s.substr(0, 1);
    for(int i = 0; i < s.size()-1; i++) {
    	// 求出从i为中心开始向左右两侧扩散的最长回文串
        string same = palindrome(s, i, i);
        // 求出从i和i+1为中心开始向左右两侧扩散的最长回文串
        string notSame = palindrome(s, i, i+1);
        ans = ans.size() < same.size() ? same : ans;
        ans = ans.size() < notSame.size() ? notSame : ans;
    }
    return ans;
}

时间复杂度为o(n*n),空间复杂度为o(1)

思路2 动态规划

数组dp[i][j]表示字符串s[i,j]区间的子串是否为回文串。 我们可以确定的是:

1. if(i == j) dp[i][j] = true
2. if(i < j) dp[i][j] = false

如何根据dp[i][j]来求解其他的值呢?

如果s[i]!=s[j],很显然dp[i][j]=false

s[i]==s[j]的情况下,如果dp[i+1][j-1]=true,此时dp[i][j]=true,此时我们可以得出状态转移方程:

dp[i][j] = dp[i+1][j-1] && s[i]==s[j]

根据上图来看,此时我们已经可以确定dp[i][j]的值了,因为先决条件已经都有了。但是我们还需要考虑到一点,在dp[i][i+1]的情况时,即j-i+1=2时,我们只需要判断s[i]和s[j]是否相等,例如求解dp[0][1]的时候,dp[1][0]=false,已经失去了参考价值。 代码如下:

string longestPalindrome(string s) {
    size_t length = s.size();
    int dp[length][length];
    int maxLen = 1;
    int start = 0;
    for(int i = 0; i < length; i++) {
        dp[i][i] = true;
    }
    for(int j = 1; j < length; j++) {
        for(int i = 0; i < j; i++) {
            if(s[i] != s[j]) {
                dp[i][j] = false;
            }else {
                if(j - i < 2) {
                    dp[i][j] = true;
                }else {
                    dp[i][j] = dp[i+1][j-1];
                }
                if(dp[i][j] && j-i+1 > maxLen) {
                    start = i;
                    maxLen = j-i+1;
                }
            }
        }
    }
    
    return s.substr(start, maxLen);
}

时间复杂度为o(n* n),空间复杂度为o(n*n)