public class LongestPalindromicSubstring {
private static String lps(String s) {
if (s == null || s.length() == 0) {
return "";
}
boolean dp[][] = new boolean[s.length()+1][s.length()+1];
// 最长子串 i长度,j位置
int maxi = 1;
int maxj = 1;
// i: 子串长度
// i 取值1和2,对应基数和偶数字符回文串最短长度的匹配
// i>2时,根据1和2的情况,以及两侧字符是否相等判定回文情况
int i = 1;
for (int j = 1; j <= s.length(); j++) {
dp[i][j] = true;
}
i = 2;
for (int j = 1; j <= s.length()-1; j++) {
if (s.charAt(j-1) == s.charAt(j)) {
dp[i][j] = true;
maxi = i;
maxj = j;
}
}
for (i = 3; i <= s.length(); i++) {
for (int j = 1; j <= s.length()+1-i; j++) {
if (s.charAt(j-1) == s.charAt(j+i-1-1) && dp[i-2][j+1]) {
dp[i][j] = true;
maxi = i;
maxj = j;
}
}
}
return s.substring(maxj-1, maxj-1+maxi);
}
public static void main(String[] args) {
System.out.println(lps("iabcbaq"));
System.out.println(lps("abcbafff"));
System.out.println(lps("cdfaaaaeablll"));
}
}
解题思路:
任意长度的回文子串,都可以去除两边的相等字符串(更高层的子问题),最终得到长度为1或2的最短回文字符串。 比如 长度为1的 a b c; 长度为2的 aa bb cc。 更长的回文字符串可以从长度为1或2的回文串拓展两侧相同字符得到
处理上述步骤1的情况, 构造子串长度为1或2时的dp数组。 长度为1统统设回文为true 即 dp[1][j]=true,长度为2的两个字符相等也设置回文为true 即 dp[2][j]=true。
对于子串长度i>3,位置为j的情况, 可以通过长度为dp[i-2][j+1]=true 加上s[j] = s[j][j+i-1] 来判定为回文。相当于判断满足长度比i小2,且起始位置为j+1的子字符串相等; 及当前字符串两侧字符相等.