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     }
java