最长回文子串问题与最长回文子序列问题类似,其不同之处在于回文子序列允许从原字串中删去若干个字符,而回文子串则不可以,其题面为
给定一个长度为N的字符串s,找到s中最长的回文子串。
实例如下:
s = "babad"
答案为"bab"或是"aba" 。
解题思路:
我们可以定义一个表达式F(i, j),其中i是字符串的开始下标,j是结束下标,F(i, j)返回的是从i到j的子字符串是否是回文子串。
根据题面的要求,我们有以下两种情况
- s[i]与s[j]相同,在该情况下,如果i和j相同,i+1=j或者i+2=j,那么F(i, j)返回的就是True, 否则返回F(i + 1, j - 1)
- s[i]与s[j]不同,在该情况下,F(i, j)返回的False
边界情况是当i>j时,F(i, j)始终返回False。
从以上表达式出发,我们可以定义一个(N+1) * (N+1)的二维数组作为DP存储,然后使用双重循环,外层循环依据字串下标从大到小,内层循环依据字串下标从小到大,来依次计算DP数组中各个元素的值。并比较所有回文子串的长度以找到最长的一个。
Java代码如下
class Solution {
public String longestPalindrome(String s) {
char[] chars = s.toCharArray();
int N = chars.length;
int maxLen = 1;
int maxStart = 0;
boolean[][] dp = new boolean[N + 1][N + 1];
for (int i = N; i >= 1; i --) {
dp[i][i] = true;
for (int j = i + 1; j <= N; j ++) {
if ((chars[i - 1] == chars[j - 1])) {
if ( j - i <= 2 || dp[i + 1][j - 1]) {
dp[i][j] = true;
int len = j - i + 1;
if (len > maxLen) {
maxLen = len;
maxStart = i - 1;
}
}
}
}
}
return s.substring(maxStart, maxStart + maxLen);
}
}