前言:区间 DP 的套路
之前的线性 DP(如斐波那契、LIS),状态往往是 dp[i],表示'以 i 结尾…'。到了回文串,我们关注的是两头。如果 s[i] 和 s[j] 相等,那就看里面的 [i+1, j-1] 是不是回文;如果不等,那就不是。所以,状态定义通常是 dp[i][j] 表示区间 [i, j] 的某种属性。
一、回文子串 (Medium)
题目描述
统计字符串中回文子串的数目。
示例:
输入:"abc" -> 输出:3 (a, b, c)
输入:"aaa" -> 输出:6 (a, a, a, aa, aa, aaa)
核心思路:区间 DP 预处理
- 状态:
dp[i][j](bool) 表示s[i...j]是否是回文串。 - 转移:
s[i] == s[j]时:- 如果
i == j(长度 1):true。 - 如果
i + 1 == j(长度 2):true。 - 如果长度 > 2:看里面
dp[i+1][j-1]。
- 如果
s[i] != s[j]时:false。
- 填表顺序:
由于
dp[i][j]依赖dp[i+1][j-1](左下角),所以i必须从大到小(从下往上)遍历,j从i开始往右遍历。
代码实现
class Solution {
public:
int countSubstrings(string s) {
int n = s.size();
// dp[i][j] 表示 s[i...j] 是否为回文
vector<vector<bool>> dp(n, vector<bool>(n, false));
int count = ;
( i = n - ; i >= ; i--) {
( j = i; j < n; j++) {
(s[i] == s[j]) {
(j - i < || dp[i + ][j - ]) {
dp[i][j] = ;
count++;
}
}
}
}
count;
}
};


