【动态规划】【最长公共子序列】nod1006 最长公共子序列Lcs

给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的)。
比如两个串为:
abcicba
abdkscab
ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符串最长的子序列。

输入

第1行:字符串A
第2行:字符串B
(A,B的长度 <= 1000)

输出

输出最长的子序列,如果有多个,随意输出1个。

输入样例

abcicba
abdkscab

输出样例

abca

思路

  • 使用一个二维数组c来存储字符串的长度。
  • 使用一个二维数组d来存储移动方向。
  • 从d[m][n]开始递归输出最长公共子序列。

代码

import java.util.Scanner;
public class nod1006 {
    private static void f(char[] a, char[] b){
        int m = a.length, n = b.length;
        // 为了规避边界检测,多开了一行一列
        int[][] c = new int[m + 1][n + 1];
        int[][] d = new int[m + 1][n + 1];
        // 初始化哨兵元素
        for(int i = 0; i <= m; i++) c[i][0] = 0;
        for(int j = 0; j <= n; j++) c[0][j] = 0;
        for(int i = 1; i <= m;i++){
            for(int j = 1; j <= n; j++){
                // 向右下角移动
                if(a[i - 1] == b[j - 1]){
                    c[i][j] = c[i - 1][j - 1] + 1;
                    d[i][j] = 0;
                }else{
                    int p = c[i - 1][j], q = c[i][j - 1];
                    if(p > q){// 向右移动
                        c[i][j] = p;
                        d[i][j] = 1;
                    }else{// 向下移动
                        c[i][j] = q;
                        d[i][j] = -1;
                    }
                }
            }
        }
        printLCS(a, d, m, n);
    }
    private static void printLCS(char[] x, int[][] d, int i, int j){
        if(i == 0 || j == 0) return;
        switch (d[i][j]){
            case 0:
                System.out.print(x[i - 1]);
                printLCS(x, d, i - 1, j - 1);
                break;
            case 1:
                printLCS(x, d, i - 1, j);
                break;
            case -1:
                printLCS(x, d, i , j - 1);
                break;
        }
    }
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        char[] a = in.nextLine().toCharArray(), b = in.nextLine().toCharArray();
        f(a, b);
    }
}

猜你喜欢

转载自blog.csdn.net/a617976080/article/details/88767177