5. 最长回文子串/C++

5. 最长回文子串/C++_第1张图片
动态规划:
i,j分别是子串的头索引和尾索引。
5. 最长回文子串/C++_第2张图片
示例1的dp表格:
5. 最长回文子串/C++_第3张图片
上一行只与下一行有关,因此可以优化成2行。
再仔细观察,发现上一行只与下一行的左边相关,所有可以优化成1行。

string longestPalindrome(string s) {
	int size = s.size();
	vector<vector<bool>> dp(size, vector<bool>(size, false));

	for (int i = 0; i < size; ++i)
		dp[i][i] = true;

	int maxLen = 1;
	int startIndex = 0;

	for (int i = size - 2; i >= 0; --i)
		for (int j = i + 1; j < size; ++j)
			if (s[i] == s[j]) {
				if (j - i == 1)
					dp[i][j] = true;
				else if (dp[i + 1][j - 1])
					dp[i][j] = true;

				if (dp[i][j]) {
					int len = j - i + 1;
					if (len > maxLen) {
						maxLen = len;
						startIndex = i;
					}
				}
			}


	return s.substr(startIndex, maxLen);
}

中心扩展算法
中心有2种,一种是一个字母,另一种是两个字母之间。也就是奇数长度子串的中心是一个字母,偶数长度子串的中心是2个字母。

class Solution {
public:
    string longestPalindrome(string s) {
        if(s.empty())
            return "";
        
        int startIndex=0;
        int maxLen=1;
        for(int i=0;i<s.size();++i){
            int len1=expandAroundCenter(s,i,i);
            int len2=expandAroundCenter(s,i,i+1);
            int len=max(len1,len2);
            if(len>maxLen){
                startIndex=i-(len-1)/2;
                maxLen=len;
            }
        }
        return s.substr(startIndex,maxLen);
    }
    
    int expandAroundCenter(string s,int left, int right){
        while(left>=0 && right<s.size() && s[left]==s[right]){
            --left;
            ++right;
        }
        return right-left-1;
    }
};

你可能感兴趣的:(动态规划,LeetCode/C++)