使用动态规划方法求最长回文串

动态规划

动态规划的思想就是,将一个大问题分解为规模更小的问题,这个小问题的解一定是可以直接求出的,并且原问题的最优解包含子问题的最优解。也就是说分治算法+贪婪算法!

寻找回文串

给定一个字符串s,找出s中的最大回文串。如
输入:s=“babad”
输出:“bab”(“aba”也可作为输出)

算法解析

设置一个二维数组 dp[i][j] ,存储字符串s的下标 ij 之间的最大回文串长度。数组长度为dp[s.length()][s.length()]

  1. 基础小问题的解:
    d p [ i ] [ i ] = 1 ; dp[i][i]=1; dp[i][i]=1;
    d p [ i ] [ i + 1 ] = { 2 if s(i) == s(i+1)  1 if s(i) != s(i+1)  dp[i][i+1]= \begin{cases} 2& \text{if s(i) == s(i+1) }\\ 1& \text{if s(i) != s(i+1) } \end{cases} dp[i][i+1]={21if s(i) == s(i+1) if s(i) != s(i+1) 
  2. 迭代关系:
    d p [ i ] [ j ] = { d p [ i + 1 ] [ j − 1 ] + 2 , if  s ( i ) = = s ( i + 1 )  and  d p [ i + 1 ] [ j − 1 ] = j − i − 1 m a x ( d p [ i + 1 ] [ j ] , d p [ i ] [ j − 1 ] ) , if  s ( i ) ! = s ( i + 1 )   dp[i][j]= \begin{cases} dp[i+1][j-1]+2, & \text {if $s(i) == s(i+1)$ and $dp[i+1][j-1]=j-i-1$} \\ max(dp[i+1][j],dp[i][j-1]), & \text{if $s(i) != s(i+1)$ } \end{cases} dp[i][j]={dp[i+1][j1]+2,max(dp[i+1][j],dp[i][j1]),if s(i)==s(i+1) and dp[i+1][j1]=ji1if s(i)!=s(i+1) 
    PS: d p [ i + 1 ] [ j − 1 ] = ( j − 1 ) − ( i + 1 ) + 1 = j − i − 1 dp[i+1][j-1]=(j-1)-(i+1)+1=j-i-1 dp[i+1][j1]=(j1)(i+1)+1=ji1 即保证 i+1 , j-1 之间的字符都满足回文要求。

java 代码实现如下:

class Solution {
    public String longestPalindrome(String s) {
        // 使用动态规划思想
        if(s.length()==1){
            return s;
        }
        int[][] dp=new int[s.length()][s.length()];
        for(int i=s.length()-1;i>=0;i--){
            dp[i][i]=1; 
            if (i<s.length()-1){
                if(s.charAt(i)==s.charAt(i+1)){
                    dp[i][i+1]=2;
                }else{
                    dp[i][i+1]=1;
                }
                System.out.print(dp[i][i+1]);
            }
            
            for(int j=i+2;j<s.length();j++){
                if(s.charAt(i)==s.charAt(j) && dp[i+1][j-1]==j-i-1){    //必须里面也是回文
                    dp[i][j]=dp[i+1][j-1]+2;
                }else{
                    if(dp[i+1][j]>dp[i][j-1]){
                        dp[i][j]=dp[i+1][j];
                    }else{
                        dp[i][j]=dp[i][j-1];
                    }
                }    
            }
        }
        int v=dp[0][s.length()-1];
        if(v==1){  //回文长度为1,即都不相等
            return String.valueOf(s.charAt(0));  // 注意char与String转换
        }else{
            String res="";
            for(int i=0;i<s.length();i++){
                for(int j=i+1;j<s.length();j++){
                    if(dp[i][j]==v && (j-i+1)==v){
                        res=s.substring(i,j+1); //包头不包尾
                    }
                }
            }
            return res;  //最后必须有返回
        }    
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值