一:题目
二:上码
class Solution {
public:
/**
思路:
动态规划五步走
1>:确定dp数组以及下标的含义
dp[i][j] 表示的是在[i,j]范围内的字串 是否是 回文子串,如果是的话那么dp[i][j] = true
2>确定dp数组的状态转移方程
那么就有两种情况 s[i] 与 s[j]是否相等,
s[i]与s[j] 不相等的话 那么dp[i][j] = false;
相等的话:
如果 i==j 的话 那么dp[i][j] = true,也就是dp[i][j]就是一个回文字符串,其实也就是网格中45度斜线
如果 i 和 j 相差为1的话 比如 aa 即s[i] = a = s[0] s[j] = a = s[1],注意这是在s[i] 和 s[j]
相等的情况下。
如果i 和 j 相差的大于1的话:比如 cabac 此时s[i] = c s[j] = c,那么我们判断该字符串到底是不是
回文字符串主要是看 aba 是不是回文字符串, 那么aba 也就是 i+1 和 j-1 即dp[i+1][j-1]
我们这里用的二维数组其实也就是 表示一个字符串
3>确定dp数组的初始化
初始化为false,因为一开始是不可能为true的,因为我们还没有进行比较。
4>:确定dp数组的遍历顺序
这是从网格的右下角开始往上
4 5 6
2 3
1
5>:举例验证:
a a a
a 1 1 1 //这里当中的第一个1 就是第一种情况 第二个就是 第二种情况 第三个就是第三情况
a 1 1
a 1
*/
int countSubstrings(string s) {
vector<vector<int>> dp(s.size(),vector<int>(s.size(),0));//这里初始化为0就是表示的是不是回文串
int ans = 0;
for (int i = s.size()-1; i >= 0; i--) {
for (int j = i; j < s.size(); j++) {
if (s[i] == s[j]) {
if (j - i <= 1) dp[i][j] = 1;//情况一情况二
else if (dp[i+1][j-1] == 1) dp[i][j] = 1;//情况三
}
}
}
// for(auto num: dp) {
// if (num == 1) ans++;
// }
for (int i = 0; i < s.size(); i++) {
for (int j = 0; j < s.size(); j++) {
if (dp[i][j] == 1) ans++;
}
}
return ans;
}
};