动态规划,最长回文子序列(java实现),输入character,算法应该返回carac

  1. 因为考试要考动态规划,所以研究了下算法,参考了网上许多资料,但是自己总结一次,印象会更加深刻。
  2. 源题目是输入character,这里换一个短点的,好分析一点,以bcdca为例。
  3. 以db[i][j]代表从字符索引i到字符索引j的最长回文子序列。当然db[0][4]就是指的bcdca的最长回文子序列。其实这个问题和最长公共子序列问题非常像。
  4. 接下来,我们考虑如何求db[0][4]的最长回文子序列。这里写图片描述
    我们很容易得到下面的递归程序
private static int getResult(char[] con, int i, int j) {
        // TODO Auto-generated method stub
        if (i==j) {
            return 1;
        }
        if (i>j) {
            return 0;
        }
        if (con[i]==con[j]) {
            return getResult(con, i+1, j-1)+2;
        }else {
            return Math.max(getResult(con, i+1, j),getResult(con, i, j-1));
        }
    }

5.于是就通过递归算出了dp[0][4]=3,于是我们很容易得出下面这张表格。在这张表格中我们能查到dp[i][j]的任意值。这个代码实现部分就是两次循环。我会在后面给出来。
这里写图片描述
6.这里我们得到了最长子回文的长度,接下来就是如何把这个字符串求出来的问题。我们简单了分析一下思路,以dp[0][4]以例,这个其它就是2+1,这里面的2就代表着有首尾相等的情况,我们把这个首尾相等时的i和j求出来。不就得到了回文的字母吗?也就是说通过还原dp的求解过程。得到回文的字母。
7.代码如下,将输入换成character.


public class huiwen {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
       String con="character";
       int[][] db=new int[9][9]; 
       //生成二维数组表
       for(int i=0;i<con.length();i++)
       {
           for(int j=i;j<con.length();j++)
           {
               db[i][j]=getResult(con.toCharArray(), i, j);
              // System.out.println("db"+"["+i+"]"+"["+j+"]"+db[i][j]);
           }

       }

       char[] res=new char[db[0][con.length()-1]];  //得到回文长度
       int m=0;        //m代表结果字符数组索引开始
       int n=res.length-1;  //n代表结果字符数组索引最后一位 
       char[] res1=con.toCharArray();  

       int i=0;
       int j=con.length()-1;
       int index=res.length-1;   //得到循环次数
       //还原dp的,从开头和结尾同时开始
       while(index>=0)
       {
           if (i<con.length()&&db[i][j]==db[i+1][j]) {
            i++;
        }else if (j>=0&&db[i][j]==db[i][j-1]) {
            j--;
        }else {
            //这种情况就代表dp[i][j]=dp[i+1][j-1]+2这种情况,这里的首和尾是相同的。取出首
            //和尾的字符填充到结果字符数组中,然后i++,j--继续从两边向中间搜索。
            res[m]=res1[i];
            res[n]=res1[j];
            i++;
            j--;
            m++;
            n--;
            index=index-2; //一次填充两个字符
        }
       }
       //将结果字符数组生成字符串
       System.out.println(String.valueOf(res));

    }

    private static int getResult(char[] con, int i, int j) {
        // TODO Auto-generated method stub
        if (i==j) {
            return 1;
        }
        if (i>j) {
            return 0;
        }
        if (con[i]==con[j]) {
            return getResult(con, i+1, j-1)+2;
        }else {
            return Math.max(getResult(con, i+1, j),getResult(con, i, j-1));
        }
    }

}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wending-Y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值