回文子串
- dp数组含义:
dp[i][j]:子串区间为[i,j],是否是回文子串 - 递推公式:
s[i]==s[j],若i与j相差1(i=j 或i,j相邻),则dp[i][j]为true;若i与j相差超过1,
则当dp[i+1][j-1]为true,dp[i][j]为true。 - 初始化:
dp[i][j]初始为false - 遍历顺序
如图,因dp[i][j]依赖于dp[i+1][j-1]。故i逆序,j正序
var countSubstrings = function(s) {
let dp=new Array(s.length).fill(false).map(()=> new Array(s.length).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((j-i)<=1){
dp[i][j]=true
res++
}else if(dp[i+1][j-1]){
dp[i][j]=true
res++
}
}
}
}
return res
};
最长回文子串
整体思路:从两边向中间分析。
- dp数组含义:
dp[i][j] :区间[i,j] 的最长回文子串的长度 - 递推公式:
s[i]==s[j],dp[i][j]=dp[i+1][j-1] +2。
s[i]!=s[j],dp[i][j]=max(dp[i+1][j],dp[i][j-1])。
- 初始化:
i==j时,dp[i][j]=1 - 遍历顺序
同上题
var longestPalindromeSubseq = function(s) {
let dp=new Array(s.length).fill(0).map(()=> new Array(s.length).fill(0))
for(let i=0;i<s.length;i++){
for(let j=0;j<s.length;j++){
if(i===j){
dp[i][j]=1
}
}
}
for(let i=s.length-1;i>=0;i--){
for(let j=i+1;j<s.length;j++){
if(s[i]===s[j]){
dp[i][j]=dp[i+1][j-1]+2
}else{
dp[i][j]=Math.max(dp[i+1][j],dp[i][j-1])
}
}
}
return dp[0][s.length-1]
};