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 由小写英文字母组成
算法思路:
考虑 动态规划,dp[i][j]
表示 区间为 [i,j]
的子串是否是回文串,递推公式如下:
-
比较
s[i]]
和s[j]
(i <= j
):- 如果不相等,则说明不是回文串
- 如果相等,分以下情况:
j == i
:单独一个字符是回文串j == i+1
:形如 aa 是回文串- 否则,比如:cbabc 则看 bab,即为
dp[i + 1][j - 1]
由
dp[i + 1][j - 1]
则遍历顺序是:i 从 后往前,j 从前往后
代码实现:
class Solution {
public int countSubstrings(String s) {
int len = s.length();
// dp[i][j]:区间为 [i,j] 的子串是否是回文串
boolean[][] dp = new boolean[len][len];
int res = 0;
for (int i = len - 1; i >= 0; i--) {
for (int j = i; j < len; j++) {
// 头尾不相同说明不是
if (s.charAt(i) != s.charAt(j)) {
dp[i][j] = false;
} else {
// j == i:单独一个字符是回文串
// j == i+1: 比如 aa 是回文串
if (j - i <= 1) {
dp[i][j] = true;
res++;
} else {
// 比如:cbabc 则看 bab,即 dp[i + 1][j - 1]
dp[i][j] = dp[i + 1][j - 1];
if (dp[i][j]){
res++;
}
}
}
}
}
return res;
}
}
Q.E.D.