给出两个字符串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);
}
}