Java (动态规划算法)解决最长公共子序列问题
最长公共子序列问题:
若给定序列X={x1,x2,…,xm},则另一序列Z={z1,z2,…,zk},是X的子序列是指存在一个严格递增下标序列{i1,i2,…,ik}使得对于所有j=1,2,…,k有:zj=xij。例如,序列Z={B,C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,7}。
给定2个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。
下面的代码计算的是,两个数组的最长公共子序列。
代码如下:
package 实验测试;
import java.util.Scanner;
public class LCSS {
public static void main(String args[]) {
int n,m;
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
m = scanner.nextInt();
int a[] = new int [m];
int b[] = new int [n];
int w = n+1;
int y = m+1;
int c[][] = new int [w][y];
int d[][] = new int [m][n];
//使用随机数来产生数组中的元素
for(int i = 0; i < a.length; i++) {
a[i] = (int)(Math.random()*10);
}
System.out.print("第一个数组为:");
for(int i = 0; i < a.length; i++) {
System.out.print(a[i]+" ");
}
System.out.println();
for(int j = 0; j < b.length; j++) {
b[j] = (int)(Math.random()*10);
}
System.out.print("第二个数组为:");
for(int i = 0; i < a.length; i++) {
System.out.print(b[i]+" ");
}
System.out.println();
System.out.print("最长公共子序列为:");
LCSlength lcs = new LCSlength();
lcs.LCS(a, b, c, d);
lcs.LCS1(m-1, n-1, a, d);
}
}
class LCSlength{
void LCS(int a[],int b[],int c[][],int d[][]) {
int i ,j;
for (i = 1; i < a.length; i++) c[i][0] = 0;
for (i = 1; i < b.length; i++) c[0][i] = 0;
for (i = 1; i < a.length; i++)
for (j = 1; j < b.length; j++)
{
if (a[i]==b[j])
{
c[i][j]=c[i-1][j-1]+1;
d[i][j]=1;
}
else if (c[i-1][j]>=c[i][j-1])
{
c[i][j]=c[i-1][j];
d[i][j]=2;
}
else
{ c[i][j]=c[i][j-1];
d[i][j]=3;
}
}
}
void LCS1(int i,int j,int a[],int d[][]) {
if (i ==0 || j==0) return;
if (d[i][j]== 1)
{
LCS1(i-1,j-1,a,d);
System.out.print(a[i]+" ");
}
else if (d[i][j]== 2)
LCS1(i-1,j,a,d);
else LCS1(i,j-1,a,d);
}
}
运行截图如下: