Given a string, your task is to count how many palindromic substrings in this string.
The substrings with different start indexes or end indexes are counted as different substrings even they consist of same characters.
Example 1:
Input: "abc" Output: 3 Explanation: Three palindromic strings: "a", "b", "c".
Example 2:
Input: "aaa" Output: 6 Explanation: Six palindromic strings: "a", "a", "a", "aa", "aa", "aaa".
Note:
- The input string length won't exceed 1000.
解题思路:运用动态规划的思路,思考如何从较小的回文子串判断较大的字符串是不是回文子串。显然形成回文子串可以看成是一个从中心向两边扩张
的过程,即确认中间的一部分是回文串后,通过向头尾添加相同字符可以形成长度+2的回文子串。
状态dp(i)(j)表示字符串s从第i位置到第j位置的子串是不是回文串,1表示是,0表示不是。
状态转移方程dp(i)(j)可以由其去除头尾后的子串dp(i+1)(j-1)来辅助判断,只有子串是回文串并且头尾相等的时候,dp(i)(j)才是回文串。
注意:1.当dp(i)(j)长度为1时显然时回文子串,长度为2时子串为空,也是回文子串。实现时要加以判断,避免出现使用dp(p)(q)出现p大于q。
2.dp(i)(j),i<=j,其他是无效情况
3.我们从dp(i+1)[]计算dp(i)[]的结果,因此从s.size()-1开始遍历i,而j则是从i位置开始递增。
class Solution {
public:
int countSubstrings(string s) {
// dp(i)(j) = isPalindromic(substring(i,j)) = (s[i]==s[j] && isPalindromic(i+1)(j-1))
// for every dp(i)(j), i <= j, we calculate dp(i)[] from dp(i+1)[], so we loop i from len-1 to 0
int ans = 0;
vector<vector<int>> dp(s.size(),vector<int>(s.size(),0));
for (int i = s.size()-1; i >= 0; i--) {
for (int j = i; j < s.size(); j++) {
dp[i][j] = (s[i] == s[j]) && (j-i < 2 || dp[i+1][j-1]);
if (dp[i][j]) {
ans++;
}
}
}
return ans;
}
};