最近做笔试题发现有许多算法题涉及到了最长公共子序列(LCS)问题,一般解决办法就是用动态规划。这里不再介绍,可以在网上查到许多相关资料。我这里要解决的是怎样找到其中所有的最长公共子序列,采用Java实现,其中的动态规划求解方法是参考网上修改后的,所有子序列打印则是自己独立完成的。
时间关系,我先把代码给摆出来吧!有问题再进行完善。
package com.mytest;
import java.util.ArrayList;
import java.util.HashSet;
//LCS: 最长公共子序列
public class Main08 {
public static void main(String[] args) {
// testMethod1();
testMethod2();
}
public static void testMethod1() {
ArrayList<Integer> arrayList1 = new ArrayList();
arrayList1.add(1);
arrayList1.add(2);
arrayList1.add(3);
ArrayList<Integer> arrayList2 = new ArrayList();
arrayList2.add(1);
arrayList2.add(2);
arrayList2.add(3);
HashSet<ArrayList> hashSet = new HashSet<>();
hashSet.add(arrayList1);
hashSet.add(arrayList2);
System.out.println(hashSet);//[[1, 2, 3]]
}
public static void testMethod2() {
String stringA = "ABCDEF";
String stringB = "AECDBFA";
solveLCS(stringA, stringB);
String stringA2 = "ABC";
String stringB2 = "CBA";
solveLCS(stringA2, stringB2);
}
public static int solveLCS(String a, String b) {
int aLen = a.length();
int bLen = b.length();
int[][] array = new int[aLen + 1][bLen + 1];
for (int i = 1; i <= aLen; i++) {
for (int j = 1; j <= bLen; j++) {
if (a.charAt(i - 1) == b.charAt(j - 1)) {
array[i][j] = array[i - 1][j - 1] + 1;
} else if (array[i][j - 1] >= array[i - 1][j]) {
array[i][j] = array[i][j - 1];
} else {
array[i][j] = array[i - 1][j];
}
}
}
//下面是打印部分
System.out.print(" ");
for (int i = 1; i <= bLen; i++) {
System.out.print(b.charAt(i - 1) + " ");
}
System.out.println();
for (int i = 0; i <= aLen; i++) {
for (int j = 0; j <= bLen; j++) {
System.out.print(array[i][j] + " ");
}
if (i != 0) {
System.out.print(a.charAt(i - 1) + " ");
}
System.out.println();
}
for (int i = aLen, j = bLen; i >= 1 && j >= 1; ) {//倒着打印
if (a.charAt(i - 1) == b.charAt(j - 1)) {
System.out.print(a.charAt(i - 1) + " ");
i--;
j--;
} else {
if (array[i][j - 1] >= array[i - 1][j]) {//>
j--;
} else {
i--;
}
}
}
System.out.println();
System.out.println(printLCSImpl(array, a, b, aLen, bLen));
return array[aLen][bLen];
}
public static HashSet<ArrayList<Character>> printLCSImpl(int[][] array, String a, String b,
int i, int j) {
if (i == 0 || j == 0) {
HashSet<ArrayList<Character>> hashSet = new HashSet<>();
hashSet.add(new ArrayList<>());
return hashSet;
}
HashSet<ArrayList<Character>> hashSet;
if (a.charAt(i - 1) == b.charAt(j - 1)) {
hashSet = printLCSImpl(array, a, b, i - 1, j - 1);
for (ArrayList<Character> arrayList : hashSet) {
arrayList.add(a.charAt(i - 1));
}
} else {
if (array[i][j - 1] > array[i - 1][j]) {
hashSet = printLCSImpl(array, a, b, i, j - 1);
} else if ((array[i][j - 1] == array[i - 1][j])) {
HashSet<ArrayList<Character>> hashSet1 = printLCSImpl(array, a, b, i, j - 1);
HashSet<ArrayList<Character>> hashSet2 = printLCSImpl(array, a, b, i - 1, j);
hashSet1.addAll(hashSet2);
hashSet = new HashSet<>(hashSet1);
} else {
hashSet = printLCSImpl(array, a, b, i - 1, j);
}
}
return hashSet;
}
}
运行结果如下,根据需要可以修改:
A E C D B F A
0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 A
0 1 1 1 1 2 2 2 B
0 1 1 2 2 2 2 2 C
0 1 1 2 3 3 3 3 D
0 1 2 2 3 3 3 3 E
0 1 2 2 3 3 4 4 F
F D C A
[[A, C, D, F]]
C B A
0 0 0 0
0 0 0 1 A
0 0 1 1 B
0 1 1 1 C
C
[[A], [B], [C]]
Process finished with exit code 0