求解最长公共子序列问题的可视化界面实现

算法思想

本程序采用算法导论224-225页(不同版本所在书页可能不一样)的自底向上的动态规划算法。
算法思想为将一个问题(求解两个序列的最长公共子序列)分解为多个子问题(求解两个序列的最长公共子序列的最长公共子序列),再将子问题分解为子问题的子问题,直至无法分解。
由于该问题具有重叠子问题性质,可以采用带备忘录的递归算法也可以采用自底向下的动态规划算法。本程序采用后者。

核心程序

private static void match() {
        m = X.length();
        n = Y.length();
        b = new char[m + 1][n + 1];
        c = new int[m + 1][n + 1];
        for (int i = 1; i <= m; i++) {
            c[i][0] = 0;
            b[i][0] = '0';
        }
        for (int j = 0; j <= n; j++) {
            c[0][j] = 0;
            b[0][j] = '0';
        }
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (X.charAt(i - 1) == Y.charAt(j - 1)) {
                    c[i][j] = c[i - 1][j - 1] + 1;
                    b[i][j] = '↖';
                } else if (c[i - 1][j] >= c[i][j - 1]) {
                    c[i][j] = c[i - 1][j];
                    b[i][j] = '↑';
                } else {
                    c[i][j] = c[i][j - 1];
                    b[i][j] = '←';
                }
            }
        }
    }
    private static void getLCS(int i, int j) {
        resulti[count] = i;
        resultj[count] = j;
        lcs[count] = b[i][j];
        count++;
        if (i == 0 || j == 0) {
            return;
        }
        if (b[i][j] == '↖') {
            getLCS(i - 1, j - 1);
        } else if (b[i][j] == '↑') {
            getLCS(i - 1, j);
        } else {
            getLCS(i, j - 1);
        }
    }

此段代码为算法导论书上224页伪代码的java实现,思想一致,代码类似,故不在此赘述。

    private static void showProcess() {
        Thread thread = new Thread(new Runnable() {

            public void run() {
                again.setEnabled(false);
                String s = "";
                for (int i = 0; i < count; i++) {
                    blabel[resulti[i] * (n + 1) + resultj[i]]
                            .setBackground(Color.GRAY);
                    blabel[resulti[i] * (n + 1) + resultj[i]].setOpaque(true);// 设置不透明
                    if (lcs[i] == '↖') {
                        s += String.valueOf(X.charAt(resulti[i] - 1));
                        LCSlabel.setText(s);
                    }
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                again.setEnabled(true);
            }

        });
        thread.start();
    }

此段代码为动态展示构造最优解的实现。主要通过线程的休眠定时改变标签的颜色和设置标签的文本造成动态的效果。线程运行时应避免重复调用该函数导致多个线程被创建并运行而造成界面错乱,因此线程要在运行时将两个按下后会调用该函数的按钮设为不可用。线程运行结束时再将按钮设为可用。

运行结果

这里写图片描述
程序运行弹出以上窗口。
两个可输入文本框中的字母序列默认为算法导论书上的两个序列,可自行删除并输入新的序列。
点击Exit退出程序。
点击Match进行匹配。
弹出以下窗口。
这里写图片描述
以上窗口分为三个区域,左右两个区域分别展示c,b两个表,中间为控制区域,点击Start
按钮动态展示构造最优解的过程。
以下为点击后的效果:
这里写图片描述
这里写图片描述
点击Again则再次展示过程。

源码

源码已上传请点击 CSDN资源Github下载


代码有问题的地方以及说错的地方还请指出,谢谢!

有任何不解的地方请留言,很乐意为您解答。


欢迎转载,但请附上原地址http://blog.csdn.net/jiaxingzheng/article/details/44225475,谢谢!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值