首先要知道什么是回文子串,定义如下:
回文子串:正着念和反着念是一样的,例如abcdcba,正着念是abcdcba反着念也是abcdcba
从题目可以得知以下两个信息:
仔细看一下回文子串,你会发现回文子串左右添加同样的字符仍构成回文子串。例如:cdc左右都加上b为bcdcb仍是一个回文子串。
假设字符串数组为str,i和j表示下标
再将思路反过来,str[i] ~ str[j] 是不是回文子串有两种情况
很明显,这一题就可以使用动态规划来解决了。可得到下面的状态转移方程:
dp[i][j]:表示 i ~ j 是不是回文子串
str[]:表示字符串数组
状态转移方程:dp[i][j] = dp[i+1][j-1] && str[i] == str[j]
优化:因为回文子串是对称的,所以忽略左下角的元素
/**
* 动态规划:最长回文子串
* 以abcbd为例子
*
*/
public String longestPalindrome(String s) {
// 特殊情况,直接返回
if ("".equals(s)) {
return null;
}
int[][] dp = new int[s.length()][s.length()];
int begin = 0; // 回文子串起始位置
int maxLen = 1; // 子串的最大长度(最小值为1)
// 开始填表格(从表格左上角开始),忽略对角线
for (int j=0; j<s.length(); j++) {
for (int i=0; i<=j; i++) {
// 对角线
if (i == j) {
dp[i][j] = 1;
} else {
boolean b = s.charAt(i) == s.charAt(j);
// 相邻且相等
if (i+1==j && b) {
dp[i][j] = 1;
} else if (b && dp[i+1][j-1] == 1) {
dp[i][j] = 1;
}
// 因int数组默认值为0,可以省略此处的else
// 判断是否需要更新子串
if (dp[i][j] == 1 && j-i+1>maxLen){
maxLen=j-i+1;
begin=i;
}
}
}
}
return s.substring(begin, begin+maxLen);
}
今天是力扣第五题~
本系列将会更新力扣的1-10题,连续更新10天!