算法设计与分析:流水线问题和最长公共子序列(Java)

最长公共子序列问题采用了递归、备忘录和动态规划来解决,流水作业问题用了Johnson

java:

最长公共子序列:

import java.util.Arrays;
import java.util.Scanner;

public class LongestCommonSubseq {
    static int[][] b = null;
    static int[][] c = null;
    static int[][] c1 = null;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.print("请输入第一个字符串:");

        //输入的字符串是从char数组的下标1处开始
        StringBuilder sb1 = new StringBuilder(" ");
        sb1 = sb1.append(sc.next());
        char[] str1 = sb1.toString().toCharArray();

        System.out.print("请输入第二个字符串:");
        StringBuilder sb2 = new StringBuilder(" ");
        sb2 = sb2.append(sc.next());
        char[] str2 = sb2.toString().toCharArray();

        //测试样例
//        char[] str1 = new char[]{' ', 'c', 'n', 'b', 'l', 'o', 'g', 's'};
//        char[] str2 = new char[]{' ', 'b', 'e', 'l', 'o', 'n', 'g'};

        b = new int[str1.length + 1][str2.length + 1];
        c = new int[str1.length + 1][str2.length + 1];
        c1 = new int[str1.length + 1][str2.length + 1];


        //初始化数组,将其全部置位-1
        initArray(c1);

        System.out.print("\n备忘录方法求得最长公共子串长度为:");
        System.out.println(LC1(str1, str2, str1.length - 1, str2.length - 1));

        System.out.print("递归方法求得最长公共子串长度为:");
        System.out.println(LC2(str1, str2, str1.length - 1, str2.length - 1));

        int max = lcsLength(str1, str2, b);
        System.out.print("动态规划法求得最长子序列长度为:" + max);
        if(max > 0)
            System.out.print(",最长子序列为:");
        else
            System.out.println(",无公共子序列");


        //从右下往左上输出子串
        lcs(str1.length - 1, str2.length - 1, str1, b);

        sc.close();
    }

    public static int lcsLength(char[] x, char[] y, int[][] b) {
        int m = x.length - 1;
        int n = y.length - 1;

        for (int i = 1; i <= m; i++) {
            c[i][0] = 0;
        }
        for (int i = 1; i <= n; i++) {
            c[0][i] = 0;
        }

        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (x[i] == y[j]) {
                    c[i][j] = c[i - 1][j - 1] + 1;
                    b[i][j] = 1;
                } else {
                    if (c[i - 1][j] >= c[i][j - 1]) {
                        c[i][j] = c[i - 1][j];
                        b[i][j] = 2;
                    } else {
                        c[i][j] = c[i][j - 1];
                        b[i][j] = 3;
                    }
                }
            }
        }
        return c[m][n];
    }

    public static void lcs(int i, int j, char[] x, int[][] b) {
        if (i == 0 || j == 0)
            return;
        if (b[i][j] == 1) {
            lcs(i - 1, j - 1, x, b);
            System.out.print(x[i]);
        } else if (b[i][j] == 2)
            lcs(i - 1, j, x, b);
        else
            lcs(i, j - 1, x, b);
    }

    //备忘录
    static int LC1(char[] x, char[] y, int i, int j) {
        if (c1[i][j] > -1)
            return c1[i][j];
        if (i == 0 || j == 0)
            c1[i][j] = 0;
        else if (x[i] == y[j])
            c1[i][j] = LC1(x, y, i - 1, j - 1) + 1;
        else
            c1[i][j] = Math.max(LC1(x, y, i, j - 1), LC1(x, y, i - 1, j));
        return c1[i][j];
    }

    //递归
    static int LC2(char[] x, char[] y, int i, int j) {
        if (i == 0 || j == 0)
            return 0;
        else if (x[i] == y[j])
            return LC2(x, y, i - 1, j - 1) + 1;
        else
            return Math.max(LC2(x, y, i, j - 1), LC2(x, y, i - 1, j));
    }

    static void initArray(int[][] a) {
        for (int[] ints : a)
            Arrays.fill(ints, -1);
    }
}

流水作业问题:

import java.util.Scanner;

public class Johnson {
    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        System.out.print("请输入作业个数:");
        int n = s.nextInt();
        int[] a = new int[n];
        int[] b = new int[n];
        int[] c = new int[n];
        System.out.println("请输入第一道工序中每个作业的时间");
        for(int i = 0; i < n; i++){
            a[i] = s.nextInt();
        }
        System.out.println("请输入第二道工序中每个作业的时间");
        for(int i = 0; i < n; i++){
            b[i] = s.nextInt();
        }
        System.out.println("最短时间为:" + flowShop(a, b, c));
    }

    public static int flowShop(int[] a, int[] b, int[] c){
        int n = a.length;
        Element[] d = new Element[n];

        for (int i = 0; i < n; i++) {
            int key = a[i] > b[i] ? b[i] : a[i];
            boolean job = a[i] <= b[i];
            d[i] = new Element(key, i, job);
        }

        mergeSort(d);

        int j = 0, k = n - 1;
        for (int i = 0; i < n; i++) {
            if(d[i].job)
                c[j++] = d[i].index;
            else
                c[k--] = d[i].index;
        }

        j = a[c[0]];
        k = j + b[c[0]];

        for (int i = 1; i < n; i++) {
            j += a[c[i]];
            k = j < k ? k + b[c[i]] : j + b[c[i]];
        }
        return k;
    }

    public static class Element implements Comparable{
        int key ;
        int index;
        boolean job;

        private Element(int key, int index, boolean job){
            this.key = key;
            this.index = index;
            this.job = job;
        }

        @Override
        public int compareTo(Object o) {
            int xkey = ((Element)o).key;
            if(key < xkey)
                return -1;
            if(key == xkey)
                return 0;
            return 1;
        }
    }

    //归并排序
    static void merge(Comparable c[], Comparable d[], int l, int m, int r) {
        int i = l, j = m + 1, k = l;
        while ((i <= m) && (j <= r)) {
            if (c[i].compareTo(c[j]) <= 0)
                d[k++] = c[i++];
            else
                d[k++] = c[j++];
        }

        if (i > m)
            for (int q = j; q <= r; q++) {
                d[k++] = c[q];
            }
        else {
            for (int q = i; q <= m; q++) {
                d[k++] = c[q];
            }
        }

    }

    static void mergePass(Comparable a[], Comparable b[], int s, int len) {
        int i = 0;
        while (i <= len - 2 * s) {
            merge(a, b, i, i + s - 1, i + 2 * s - 1);
            i = i + 2 * s;
        }
        if (i + s < len) {
            merge(a, b, i, i + s - 1, len - 1);
        } else {
            for (int j = i; j < len; j++) {
                b[j] = a[j];
            }
        }
    }

    static void mergeSort(Comparable a[]) {
        int len = a.length;
        Comparable[] b = new Comparable[len];

        int s = 1;

        while (s < len) {
            mergePass(a, b, s, len);
            s += s;
            mergePass(b, a, s, len);
            s += s;
        }
    }
}

qq:1351006594

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,我会尽力回答你的问题。 最公共序列问题是指在两个字符串中找到一个最的公共序列,即两个字符串中都存在的、度最序列。动态规划算法是解决该问题的常用方法。 下面是Java代码实现: ```java public class LongestCommonSubsequence { public static String findLCS(String s1, String s2) { int[][] dp = new int[s1.length() + 1][s2.length() + 1]; // 初始化第一行和第一列 for (int i = 0; i <= s1.length(); i++) { dp[i][0] = 0; } for (int j = 0; j <= s2.length(); j++) { dp[0][j] = 0; } // 计算dp数组 for (int i = 1; i <= s1.length(); i++) { for (int j = 1; j <= s2.length(); j++) { if (s1.charAt(i - 1) == s2.charAt(j - 1)) { dp[i][j] = dp[i - 1][j - 1] + 1; } else { dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); } } } // 构造最公共序列 StringBuilder sb = new StringBuilder(); int i = s1.length(); int j = s2.length(); while (i > 0 && j > 0) { if (s1.charAt(i - 1) == s2.charAt(j - 1)) { sb.append(s1.charAt(i - 1)); i--; j--; } else if (dp[i - 1][j] > dp[i][j - 1]) { i--; } else { j--; } } return sb.reverse().toString(); } public static void main(String[] args) { String s1 = "ABCBDAB"; String s2 = "BDCABA"; String lcs = findLCS(s1, s2); System.out.println(lcs); } } ``` 代码中,我们使用一个二维数组 `dp` 来存储最公共序列度。`dp[i][j]` 表示字符串 `s1` 的前 `i` 个字符和字符串 `s2` 的前 `j` 个字符中最公共序列度。然后,我们遍历整个 `dp` 数组,计算出最公共序列度。最后,我们根据 `dp` 数组构造最公共序列。 希望这个回答能够解决你的问题。如果你还有其他问题,可以继续问我。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Aaron_Liu0730

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

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

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

打赏作者

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

抵扣说明:

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

余额充值