5. 最长回文子串

2刷。感觉看矩阵不太好理解,还是按原来的。
动态规划假设子问题已经解决,看最后一步。

class Solution {
    //dp[i][j],ss[i...j]是不是回文子串
    //递推
    //dp[i][j]=dp[i+1][j-1]&&s[i]==s[j]
    //注意循环遍历的顺序。
    public String longestPalindrome(String s) {
       char[] ss=s.toCharArray();
       boolean[][] dp=new boolean[ss.length][ss.length];
       int max=0;
       int left=0,right=0;
       for(int i=0;i<ss.length;i++)
           dp[i][i]=true;
        // 不要想成矩阵,就把i,j当成是字符数组下标。固定最后一个字符j,i子串首个字符的下标位置
        // i+1,j-1就是i和j中间子串的首尾下标
        // i+1>j-1在i<j的前提下就是i和j相邻才会出现的情况
        // 还有一个问题是,这种思路如何解释dp[i+1][j-1]一定比dp[i][j]先计算出来(状态转移能够成立需要这个前提)
        // dp[i][j]的子问题为什么是dp[i+1][j-1]
        // 那还是要看矩阵
        /*
          j  0   1   2   3   4   5
        i  -------------------------
        0 |  T   F   F   F   F   F  | 
        1 |      T   F   F   F   F  | 
        2 |          T   F   F   F  | 
        3 |              T   F   F  | 
        4 |                  T   F  | 
        5 |                      T  | 
        i+1,j-1在i,j的左下角,已知对角线为True,这是初始条件,其他位置就可以被推导出来了~~~形如(i,i+1)即只有2个字符的
        子串是不是回文不由d[i+1][j-1]而是另一个转移方程arr[i]==arr[j]决定
        */
       for(int j=1;j<ss.length;j++){//实际上是固定最后一个,变换起点
       //不能是固定起点,变换终点。这也不是解动态规划的思路:看最后一步
           for(int i=0;i<j;i++){//对角线以上的
                if(i+1<=j-1)
                    dp[i][j]=dp[i+1][j-1]&&(ss[i]==ss[j]);
                else{//两个元素
                    dp[i][j]=(ss[i]==ss[j]);
                }
                if(dp[i][j]&&max<(j-i+1)){
                     max=j-i+1;
                     left=i;
                     right=j;
                }
           }
       }
       return s.substring(left,right+1);

    }
}

posted @ 2021-06-05 17:12  wsshub  阅读(34)  评论(0)    收藏  举报