class Solution {
//最长回文子串,动态规划,
//dp[i][j]代表从i到j的最长回文子串的长度
//初始化的dp[i][i] = 1
//遍历顺序:按长度遍历,再从左到右按索引遍历
public String longestPalindrome(String s) {
// char[] arr = s.toCharArray();
// 反序与原始字符串相同,动态规划
// 如果s.substring(i,j)是回文子串,则s.substring(i+1,j-1)一定也是回文子串
// 每一个字符一定是回文子串,判断2个长度的字符串是不是回文子串只需要判断两个字符是否相等
// 用二维哈希表来表示所有子串是不是回文子串,行下标与列下标的最大差值代表长度
// int len = arr.length;
// if(len < 2){ //长度小于2说明是动态数组
// return s;
// }
// boolean[][] hash = new boolean[len][len];
// int maxLen = 1;
// int begin = 0;
// for(int i = 0 ; i < len; i++){
// hash[i][i] = true; // 单个字符一定是回文串
// }
// for(int L = 2; L <= len; L++){ //L代表的长度
// for(int i = 0 ; i < len; i++){ //左边界,字符串的起始下标
// int j = L + i - 1; //子字符串的长度为L, j - i + 1 = L;
// if( j >= len){
// break;
// }
// if(arr[i] != arr[j]){ // 子字符串长度小于等于3的时候,只需要看左右边界
// hash[i][j] = false; // 子字符串长度>3的时候,hash[i][j] = hash[i+1][j-1];
// }else {
// if(L <= 3){
// hash[i][j] = true;
// }else{
// hash[i][j] = hash[i+1][j-1];
// }
// }
// if(hash[i][j]&& L > maxLen){
// maxLen = L;
// begin = i;
// }
// }
// }
// return s.substring(begin,begin+maxLen); // 不包括begin+maxLen
int n = s.length();
if (n == 1) {
return s;
}
boolean[][] dp = new boolean[n][n];
for (int i = 0; i < n; i++) {
dp[i][i] = true;
}
int maxLen = 1;
int begin = 0;
for (int i = 2; i <= n; i++) {
for (int j = 0; j < n;j++) {
int k = j + i - 1;
if(k >= n) {
break;
}
if (i <= 3) {
if (s.charAt(j) == s.charAt(k)) {
dp[j][k] = true;
}else {
dp[j][k] = false;
}
} else {
if (s.charAt(j) == s.charAt(k)) {
dp[j][k] = dp[j +1][k - 1] ;
}else {
dp[j][k] = false;
}
}
if (dp[j][k] && i > maxLen ) {
maxLen = i;
begin = j;
}
}
}
return s.substring(begin,begin+maxLen);
}
}