LeetCode Day59

74 阅读3分钟

647. 回文子串

给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。

示例 1: 输入:s = "abc" 输出:3 解释:三个回文子串: "a", "b", "c" 示例 2: 输入:s = "aaa" 输出:6 解释:6个回文子串: "a", "a", "a", "aa", "aa", "aaa"

提示:

  • 1 <= s.length <= 1000
  • s 由小写英文字母组成

思路

为了统计字符串中回文子串的数量,我们可以使用动态规划的方法。这里是一个可能的解决方案的步骤:

  1. 确定dp数组以及下标的含义
  • dp[i][j] 表示字符串从索引 ij 的子串是否是回文串。如果是回文串,dp[i][j]true,否则为 false
  1. 确定递推公式
  • 如果 s[i] == s[j],那么我们需要检查里面的子串 s[i+1...j-1] 是否是回文串,这可以通过 dp[i+1][j-1] 来判断。如果里面的子串是回文串,那么 dp[i][j] 也是回文串。
  • 如果 s[i] != s[j],那么 dp[i][j] 显然不是回文串。
  • 递推公式为:dp[i][j] = (s[i] == s[j]) && (j - i < 3 || dp[i+1][j-1])
  1. dp数组如何初始化
  • 所有的 dp[i][i] 都应该初始化为 true,因为每个单独的字符都是回文串。
  • 其余的 dp[i][j] 初始化为 false
  1. 确定遍历顺序
  • 由于 dp[i][j] 依赖于 dp[i+1][j-1],我们需要从下往上,从左到右进行遍历。
  1. 举例推导dp数组
  • 以字符串 s = "aaa" 为例,dp[0][0]dp[1][1]dp[2][2] 都应该为 true
  • dp[0][1] 会检查 s[0]s[1] 是否相等,以此类推。

题解

class Solution {
public:
    int countSubstrings(string s) {
        int n = s.size();
        vector<vector<bool>> dp(n, vector<bool>(n, false));
        int count = 0;

        for (int i = n - 1; i >= 0; --i) {
            for (int j = i; j < n; ++j) {
                if (s[i] == s[j] && (j - i < 3 || dp[i + 1][j - 1])) {
                    dp[i][j] = true;
                    count++;
                }
            }
        }

        return count;
    }
};

516. 最长回文子序列

给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。 子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。

示例 1: 输入:s = "bbbab" 输出:4 解释:一个可能的最长回文子序列为 "bbbb" 。 示例 2: 输入:s = "cbbd" 输出:2 解释:一个可能的最长回文子序列为 "bb" 。

提示:

  • 1 <= s.length <= 1000
  • s 仅由小写英文字母组成

思路

  1. 确定dp数组以及下标的含义
  • dp[i][j] 表示字符串从索引 ij 的子序列中,最长回文子序列的长度。
  1. 确定递推公式
  • 如果 s[i] == s[j],那么 dp[i][j] = dp[i+1][j-1] + 2
  • 如果 s[i] != s[j],那么 dp[i][j] = max(dp[i+1][j], dp[i][j-1])
  1. dp数组如何初始化
  • 所有的 dp[i][i] 都应该初始化为 1,因为每个单独的字符都是一个长度为1的回文子序列。
  • 其余的 dp[i][j] 初始化为 0
  1. 确定遍历顺序
  • 由于 dp[i][j] 依赖于 dp[i+1][j-1]dp[i+1][j]dp[i][j-1],我们需要从下往上,从左到右进行遍历。
  1. 举例推导dp数组
  • 以字符串 s = "bbbab" 为例,dp[0][4] 会检查 s[0]s[4] 是否相等,以此类推。

题解

class Solution {
public:
    int longestPalindromeSubseq(string s) {
        int n = s.size();
        vector<vector<int>> dp(n, vector<int>(n, 0));

        // 初始化dp数组
        for (int i = 0; i < n; ++i) {
            dp[i][i] = 1;
        }

        // 从下往上,从左到右遍历
        for (int i = n - 1; i >= 0; --i) {
            for (int j = i + 1; j < n; ++j) {
                if (s[i] == s[j]) {
                    dp[i][j] = dp[i + 1][j - 1] + 2;
                } else {
                    dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);
                }
            }
        }

        return dp[0][n - 1];
    }
};