回文子串
TIP
给你一个字符串s
,请你统计并返回这个字符串中 回文子串 的数目。
回文字符串 是正着读和倒过来读一样的字符串。
子字符串 是字符串中的由连续字符组成的一个序列。
具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。
思路

布尔类型的
dp[i][j]
:表示区间范围[i,j]
(注意是左闭右闭)的子串是否是回文子串,如果是dp[i][j]
为true
,否则为false
。当
s[i]
与s[j]
相等时,这就复杂一些了,有如下三种情况- 情况一:下标
i
与j
相同,同一个字符例如a
,当然是回文子串 - 情况二:下标
i
与j
相差为1
,例如aa
,也是回文子串 - 情况三:下标:
i
与j
相差大于1的时候,例如cabac
,此时s[i]
与s[j]
已经相同了,我们看i
到j
区间是不是回文子串就看aba
是不是回文就可以了,那么aba
的区间就是i+1
与j-1
区间,这个区间是不是回文就看dp[i + 1][j - 1]
是否为true。
- 情况一:下标
初始化:
dp[i][j]
初始化为false一定要注意遍历顺序!!
如果这矩阵是从上到下,从左到右遍历,那么会用到没有计算过的
dp[i + 1][j - 1]
,也就是根据不确定是不是回文的区间[i+1,j-1]
,来判断了[i,j]
是不是回文,那结果一定是不对的。所以一定要从下到上,从左到右遍历,这样保证
dp[i + 1][j - 1]
都是经过计算的。jsvar countSubstrings = function(s) { let dp = Array(s.length+1).fill().map(() => Array(s.length + 1).fill(false)); let res = 0 for(let i=s.length-1;i>=0;i--){ for(let j=i;j<s.length;j++){ if(s[i]===s[j]){ if(i===j || j-i===1){ dp[i][j] = true res++ } else{ if(dp[i+1][j-1]){ dp[i][j] = true res++ } } } } } return res };