给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。
回文字符串 是正着读和倒过来读一样的字符串。
子字符串 是字符串中的由连续字符组成的一个序列。
具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。
示例 1:
输入:s = “abc”
输出:3
解释:三个回文子串: “a”, “b”, “c”
示例 2:
输入:s = “aaa”
输出:6
解释:6个回文子串: “a”, “a”, “a”, “aa”, “aa”, “aaa”
快速解题关键思路:即需要判断该字串所有的子串是不是回文字串
- 要确定一个字符串是不是回文子串,就要确定其子串是否是回文子串,如果其子串是回文子串,且子串两侧的字符相同,那么该字符串一定会回文子串。
- 要记录子串是否是回文子串,就要选择动态规划解决问题。因为在动态规划中,当前状态是由前一状态推出来的。
三种情况:
- 一个字符时,一定是回文子串;
- 两个字符时,如果两个字符相同,那么就是回文子串;
- 超过两个字符时,如果首尾字符相同,且其子串是回文子串,那么它一定是回文子串。
初始化一个 dp 数组,用来存储每一个子串是否是回文子串的状态。
class Solution {
public int countSubstrings(String s) {
// 将字符串转换成字符数组,提高判断效率
char[] sArr =s.toCharArray();
int n = sArr.length;
// 记录回文字串的数量
int result = 0;
// 存储每一个子串是否是回文字串
boolean [][] dp = new boolean[n][n];
for(int i = n - 1 ; i >= 0; i--){
for(int j = i; j < n; j++){
// 如果两个字符相同
if(sArr[i] == sArr[j]){
// 单个字符和两个相邻的字符相同,一定是回文子串。
if(j - i <= 1){
result ++;
dp[i][j] = true;
}// 超过两个字符,就要判断其子串是否是回文子串了,如果其子串是回文子串,那么它也是回文子串。
else if(dp[i + 1][j - 1]){
result ++;
dp[i][j] = true;
}
}
}
}
return result;
}
}