区间 DP 入门:从中心向两边扩散
一、前言:区间 DP 的套路
开篇:之前的线性 DP(如斐波那契、LIS),状态往往是
dp[i],表示"以i结尾…"。思维升级:到了回文串,我们关注的是两头。
s[i]和s[j]如果相等,那就看里面的[i+1, j-1]是不是回文;如果不等,那就不是。所以,状态定义通常是dp[i][j]表示区间[i, j]的某种属性。
二、回文子串 (Medium)
2.1 题目描述
题目链接:647. 回文子串
描述:统计字符串中回文子串的数目。
示例:
- 输入:
"abc"-> 输出:3(a,b,c)- 输入:
"aaa"-> 输出:6(a,a,a,aa,aa,aaa)
2.2 核心思路:区间 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开始往右遍历。
2.3 代码实现
class Solution {
public:
int countSubstrings {
n = s.();
vector<vector<>> (n, <>(n, ));
count = ;
( i = n - ; i >= ; i--) {
( j = i; j < n; j++) {
(s[i] == s[j]) {
(j - i < || dp[i + ][j - ]) {
dp[i][j] = ;
count++;
}
}
}
}
count;
}
};

