《JAVA》中利用《动态规划》实现《最小公共子序列》

本文介绍了如何使用Java实现动态规划算法解决字符串A和B的最小公共子序列问题。通过动态规划法避免了递归带来的重复计算,详细阐述了算法的推导过程,并提供了算法伪代码和具体实现。
摘要由CSDN通过智能技术生成

动态规划:递归导致的问题,很多小问题重复出现,所以有了动态规划算法,让许多小问题可以重复利用,减少算法的重复计算。

穷举法
可使用穷举法求解字符串A和B的最长公共子序列长度,算法描述如下:
列举字符串A的除空串之外的所有子序列,设A的长度为n,A共有2n-1个子序列。
例A=”abcd”,可能的24-1=15个子序列为:
a、b、c、d、(4个)
ab、ac、ad、bc、bd、cd、(6个)
abc、abd、acd、bcd、(4个)
abcd (1个)

动态规划法
设A=a1a2…an、B=b1b2…bm,L[i,j]表示a1a2…ai和b1b2…bj的最长公共子序列长度,很容易证明下面的观察结论:
如果i和j都大于0,那么
若ai=bj,a1…a(i-1)和b1…b(j-1)的最长子序列 + 1
L[i,j]=L[i-1,j-1]+1;
若ai≠bj,求取a1….ai和b1…b(j-1)的最长子序列
求取a1…a(i-1)和b1…b(j)的最长子序列
然后求取二者的最大值,即
L[i,j]=max(L[i,j-1],L[i-1,j])。

动态规划实现 推导公式:

这里写图片描述

算法分析:
这里写图片描述

动态规划特点:自下往上求解小问题

动态规划法求解最长公共子序列。对于每对i和j的值,用一个二维数组L[0..m,0..n]来存放L[i,j]的值。
⑴设字符串A=a1a2…an,字符串B=b1b2…bm。以字符串A为y轴,字符串B为x轴。
⑵首先从A子串只有一个字符开始,计算出a1和B中各子串的最大公共子序列长度;然后逐个增加A子串中的字符,分别计算出当前A子串和B各子串的最大公共子序列长度;直至A的全部字符。
⑶L[i,j]表示A子串a1a2…ai(1≤i≤n)和B子串b1b2…bj(1≤j≤m)的最大公共子序列长度。
1. if ai=bj then
2. L[i,j]←L[i-1,j-1]+1
3. else
4. L[i,j]←max{L[i,j-1],L[i-1,j]}
5. end if

算法伪代码:
输入:字符串A和B,设A和B的长度分别为n和m。
输出:A和B的最长公共子序列的长度
1. for i←0 to n //字符串A为y轴
2. L[i,0]←0 //字符串B为空
3. end for
4. for j←0 to m //字符串B为x轴
5. L[0,j]←0 //字符串A为空
6. end for
7. for i←1 to n //A子串中字符逐个增加
8. for j←1 to m //当A子串确定,B子串中字符逐个增加。
9. if ai=bj then L[i,j]←L[i-1,j-1]+1 //i-1表示上一行
10. else L[i,j]←max{L[i,j-1],L[i-1,j]} //j-1表示前一列
11. end if
12. end for
13. end for
14. return L[m,n] //返回最长公共子序列长度

算法方法
这里写图片描述
这里写图片描述

算法具体实现:

package Test5;

/**
 * 最大公共子序列
 * 
 * @author Mr.洛洛
 * @by 2015.12.20
 */
public class LCS {
   
    static String strA = "zxyxyx";
    static String strB = "xyyzx";

    public static void main(String args[]) {
        int[][] arrs = new int[strA.length() + 1][strB.length() + 1];
        int maxLCSLength = LCSLength(arrs);
        printLCS(arrs);
        System.out.println("\n\t最长公共子序列长度为:" + maxLCSLength);
    }

    /**
     * 最长公共子序列算法实现
     * 
     * @param arrs
     */
    public static int LCSLength(int[][] arrs) {
        for (int i = 0; i < arrs.length; i++) {
            System.out.println("==================最长公共子序列算法===================");
            System.out.println("\n======================第 " + (i + 1)
                    + " 次循环======================");
            if (i > 0) {
                System.out.println("strA = " + strA.substring(0, i)
                        + " , strB = ' " + strB + " '");
            } else {
                System.out.println
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值