基本思想:
字符串s的最长回文子串,我们用dp(i,j)表示从下标i到下标j(包含)子串的是否是回文子串,然后将s的所有子串都判断一遍,最后找出最长的回文子串
dp(i,j)求法:
使用动态规划求dp(i,j),状态转移方程为:
p(i,j) = p(i+1,j-1) && s[i]==s[j] (i>=j),即如果s[i,j]为回文字符串,则s[i]==s[j],且s[i+1,j-1]为回文字符串,动态规划的边界条件为dp(i,i)=true,dp(i,i+1)=(s[i]==s[i+1])
具体实现:
用一个boolean二维数组dp来记录保存s的所有子串是否是回文子串,构建dp数组的时候记录并更新一个最长回文子串,构建完成后输出记录的子串即可
代码
代码:
public String longestPalindrome(String s) {
int length = s.length();
boolean[][] dp = new boolean[length][length];
int max = 0;//记录最长回文子串的长度
StringBuilder result = null;//记录最长回文子串
for(int len=0;len<length;len++){//子串长度从1开始循环
for(int i=0;i+len<length;i++){//下标从0开始检查回文子串
if(len==0){//子串长度为1时的情况
dp[i][i+len]=true;
}else if(len==1){//子串长度为2时的情况
dp[i][i+len]=s.charAt(i) == s.charAt(i+len);
}else{//使用动态转移方程求子串是否是回文子串
dp[i][i+len]=s.charAt(i) == s.charAt(i+len)&&dp[i+1][i+len-1];
}
if(dp[i][i+len]){//判断最长子串是否更新
max = (len+1)>max?(len+1):max;
result = new StringBuilder(s.substring(i,i+len+1));
}
}
}
return result.toString();
}
总结:动态规划就是减少了检查回文子串时的重复计算,用空间换取时间,这种思想和非关系数据库redis做缓存类似