最长公共子序列的问题

题目:

给定两个字符串str1和str2,返回两个字符串的最长公共子序列。
举例str1=”1A2C3D4B56”,str=“B1D23CA45B6A”。123456或者12C4B6都是最长公共子序列,返回哪一个都行。

思路:

此题可以采用动态规划的思想来解。首先要构造一个矩阵Matrix[str1.length()][str2.length()]。以str1为行,str2为列。之后构造数组dp[str1.length()][str2.length()]用于记录最长匹配字符串的长度。首先要算出dp[0][0]的值之后算出第一行或者是第一列的dp值。dp[0][0]的值通过以下公式计算:

dp[0][0] = str1.charAt(0) == str2.charAt(0)?1:0;

之后计算第一列的最长公共序列的长度,实质上就是比较str2[0]与str1[0~i-1]。若str2[0]与某一项str1[x]相等则设dp[x][0]为1.之后的dp[i+1~str1.length()-1]均为1.因为比较的是str2[0],长度最大为1.列上的同理。

之后要解决i,j大于等于1上的数据了。需要考虑三种情况:

  • str1[i]!= str2[j],dp[i-1][j]大于dp[i][j-1],则dp[i][j]为dp[i-1][j].
  • str1[i]!= str2[j],dp[i][j-1]大于dp[i-1][j],则dp[i][j]为dp[i][j-1].
  • str1[i]== str2[j],dp[i][j] = dp[i-1][j-1]+1与dp[i][j]的最大值。

解题代码:

public int [][]Solution(String str1,String str2){
        int [][] dp = new int [str1.length()][str2.length()];
        for(int i=0;i<str1.length();i++){
            Arrays.fill(dp[i], 0);
        }
        dp[0][0] = str1.charAt(0) == str2.charAt(0)?1:0;
        for(int i=1;i<str1.length();i++){
            dp[i][0] = Math.max(dp[i-1][0], str1.charAt(i) == str2.charAt(0)?1:0);
        }
        for(int j=1;j<str2.length();j++){
            dp[0][j] = Math.max(dp[0][j-1], str1.charAt(0) == str2.charAt(j) ?1:0);
        }
        for(int i=1;i<str1.length();i++){
            for(int j=1;j<str2.length();j++){
                dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
                if(str1.charAt(i) == str2.charAt(j)){
                    dp[i][j] = Math.max(dp[i][j], dp[i-1][j-1]+1);
                }
            }
        }
        return dp;
    }

public static void main(String[] args) {
        // TODO Auto-generated method stub
        try {
            problem1 p1 = problem1.class.newInstance();
            String str1 = new String("1A2C3D4B56");
            String str2 = new String("B1D23CA45B6A");
            int [][] dp = p1.Solution(str1, str2);
            int m = str1.length()-1;
            int n = str2.length()-1;
            char [] res = new char[dp[m][n]];
            int index = res.length-1;
            while(index >= 0){
                if(m>0 && dp[m][n] == dp[m-1][n]){
                    m--;
                }else if(n>0 && dp[m][n] == dp[m][n-1]){
                    n--;
                }else{
                    res[index--] = str1.charAt(m);
                    m--;
                    n--;
                }
            }
            System.out.println(String.valueOf(res));
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值