leetcode 5:给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: "dcabac"
输出: "cabca",从左边读和从右边读一样


1.数组str[n]的dp[i][j]要是回文串的话,要满足str[i]等于str[j],且dp[i+1][j-1]也必须是回文串,否则dp[i][j]不可能是回文串;
dp[i][j]是不是回文,取决于dp[i+1][j-1]是不是回文,且str[i]是不是等于str[j];
dp[i-1][j-1]是不是回文,取决于dp[i+2][j-2]是不是回文,且str[i-1]是不是等于str[j-1];
......
层层递推,最终递推到dp[1][1]和dp[0][0],而这些初始状态是已知的。
2.所以,对于字符串str,假设dp[i,j]=1表示str[i...j]是回文子串,那个必定存在dp[i+1,j-1]=1。这样最长回文子串就能分解成一系列子问题,构造状态转移方程

上面的状态转移方程表示,当str[i]=str[j]时,如果str[i+1...j-1]是回文串,则str[i...j]也是回文串;如果str[i+1...j-1]不是回文串,则str[i...j]不是回文串。
初始状态 dp[i][i]=1,单个字符串也算回文;dp[i][i+1]=1 if str[i]==str[i+1],两个相同的字符串也算回文
3.有初始状态和递推方程,就可以算出最长回文
1 public static String longestPalindrome(String s) { 2 if(s == null || s.equals("")){ 3 return s; 4 } 5 int[][] dp = new int[s.length()][s.length()]; 6 int left=0,right=0; 7 for(int i = 0; i<s.length(); i++) dp[i][i] = 1; 8 for(int i = s.length()-1; i>=0; i--){ 9 for(int j = i+1; j<s.length(); j++){ 10 if(s.charAt(i) == s.charAt(j)) { 11 if(j-i == 1){ 12 dp[i][j] = 1; 13 } 14 else{ 15 dp[i][j] = dp[i+1][j-1]; 16 } 17 }else{ 18 dp[i][j] = 0; 19 } 20 if(dp[i][j]==1){ 21 if(j-i>=right-left){ 22 left = i; 23 right = j; 24 } 25 } 26 } 27 } 28 String maxStr = s.substring(left,right+1); 29 System.out.println("最长回文子串:"+maxStr); 30 return maxStr; 31 }