最长公共子序列 动态规划

最长公共子序列 动态规划

  • 若给定序列X={x1,x2,…,xm},则另一序列Z={z1,z2,…,zk},是X的子序列是指存在一个严格递增下标序列{i1,i2,…,ik}使得对于所有j=1,2,…,k有:zj=xij。例如,序列Z={B,C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,7}。

  • 给定2个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。

  • 给定2个序列X={x1,x2,…,xm}和Y={y1,y2,…,yn},找出X和Y的最长公共子序列。

@SuppressWarnings("all")
public class Longest_common_subsequence {//最长公共子序列 动态规划
    public static void main(String args[]){
        char []a = {'A','C','T','C','C','T','A','G'};
        char []b = {'C','A','T','T','C','A','G','C'};
        int [][]arr = new int[a.length + 1][b.length + 1];
        int [][]arr1 = lcslength(a.length + 1,b.length + 1,a,b,arr);//记录公共子序列的位置
        System.out.print("最长公共子序列为:");
        lcs(arr1.length - 1,arr1[0].length - 1,a,arr1);
    }
    static void lcs(int i,int j,char []a,int [][]arr){//输出公共子序列
        if(i == 0||j == 0)return;
        if(arr[i][j] == 1){
            lcs(i - 1,j - 1,a,arr);//先递归,在输出
            System.out.printf("%c",a[i - 1]);
        }
        else if(arr[i][j] == 2){
            lcs(i - 1,j,a,arr);
        }
        else {
            lcs(i,j - 1,a,arr);
        }
    }
    static int[][]lcslength(int n,int m,char []a,char []b,int [][]arr){//寻找公共子序列并记录
        int [][]c = new int[n][m];
        for(int i = 0;i < n;i++){//初始化 多余
            c[i][0] = 0;
        }
        for(int j = 0;j < n;j++){
            c[0][j] = 0;
        }

        for(int i = 1;i < c.length;i++){
            for(int j = 1;j < c[0].length;j++){
                if(a[i - 1] == b[j - 1]){//1表示左上角
                    c[i][j] = c[i - 1][j - 1] + 1;
                    arr[i][j] = 1;
                }
                else{//2 表示上方
                    if(c[i - 1][j] > c[i][j - 1]){
                        c[i][j] = c[i -1][j];
                        arr[i][j] = 2;
                    }
                    else{//3 表示左边
                        c[i][j] = c[i][j - 1];
                        arr[i][j] = 3;
                    }
                }
            }
        }
        System.out.println("最长公共子序列长度为:" + c[n - 1][m - 1]);
        return arr;
    }
}
参考博客:

https://blog.csdn.net/weixin_40673608/article/details/84262695?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163937751116780366598863%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=163937751116780366598863&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v1~rank_v31_ecpm-2-84262695.pc_search_result_cache&utm_term=%E6%9C%80%E9%95%BF%E5%85%AC%E5%85%B1%E5%AD%90%E5%BA%8F%E5%88%97+%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92&spm=1018.2226.3001.4187

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值