最长公共子序列

原创


动态规划解最长公共子序列问题

设序列一的序列为:Ai(1<=i<=n)

序列二的序列为:Bj(1<=j<=m)

最长公共子序列为:Ck(1<=k<=z)

能用动态规划解的题目都是可以将原规模的题分解成子问题规模,公共子序列问题可以这样分解:

如果存在An==Bm==Cz,则Ai(1<=i<=n-1)和Bj(1<=j<=m-1)的最长公共子序列为:Ck(1<=k<=z-1)

如果存在An!=Bm,且An!=Cz,则Ai(1<=i<=n-1)和Bj(1<=j<=m)的最长公共子序列为:Ck(1<=k<=z)

如果存在An!=Bm,且Bm!=Cz,则Ai(1<=i<=n)和Bj(1<=j<=m-1)的最长公共子序列为:Ck(1<=k<=z)

利用上述的关系式我们自顶向下的求最长公共子序列长度。

设数组F[ i ][ j ]表示序列一的长度为i,序列二的长度为j时的最长公共子序列长度,显而易见,当i==0或者j==0时,

即存在其中一个序列没有元素时,F[i][j]都是0,然后利用上述的关系式可以继续往下求。

当A[i]==B[j]时,F[i][j]=F[i-1][j-1]

当A[i-1]!=B[j]时,max{ F[i][j-1],F[i-1][j] }

上面为什么要选出一个最大的呢?

假如是An!=Bm,且An!=Cz这种情况,我们可以知道应该铲除Ai的最后一个元素An,公共子序列长度和原规模

问题的公共子序列长度是相同的,但是如果铲除了Bm,则公共子序列长度肯定会小于等于原规模的公共子序列长度。

为什么会小于等于自己理解了!

 1 import java.util.Scanner;
 2 
 3 public class 算法分析与设计3_1 {
 4     
 5     static void LCS(int m,int n,int A[],int b[][]){
 6         if(m==0 || n==0)return;
 7         if(b[m][n]==1){
 8             LCS(m-1,n-1,A,b);
 9             System.out.print(A[m]+" ");
10         }else if(b[m][n]==2){
11             LCS(m-1,n,A,b);
12         }else{
13             LCS(m,n-1,A,b);
14         }
15     }
16 
17     static void LCSLength(int A[],int B[],int C[][],int m,int n,int b[][]){
18         for(int i=0;i<=m;i++){
19             C[i][0]=0;    //B序列无元素 
20         }
21         for(int i=0;i<=n;i++){
22             C[0][i]=0;    //A序列无元素
23         }
24         for(int i=1;i<=m;i++){
25             for(int j=1;j<=n;j++){
26                 if(A[i]==B[j]){
27                     C[i][j]=C[i-1][j-1]+1;
28                     b[i][j]=1;    //斜上方 
29                 }else if(C[i-1][j]>=C[i][j-1]){
30                     C[i][j]=C[i-1][j];
31                     b[i][j]=2;    //上一行 
32                 }else{
33                     C[i][j]=C[i][j-1];
34                     b[i][j]=3;    //上一列 
35                 }
36             } 
37         }
38         LCS(m,n,A,b);
39     }
40 
41     public static void main(String[] args) {
42         Scanner reader=new Scanner(System.in);
43         int A[]=new int[1000];
44         int B[]=new int[1000];
45         int C[][]=new int[1000][1000];
46         int b[][]=new int[1000][1000];
47         System.out.print("输入第一个序列的大小:");
48         int A_size=reader.nextInt();
49         System.out.print("输入第一个序列的值:");
50         for(int i=1;i<=A_size;i++){
51             A[i]=reader.nextInt();
52         }
53         System.out.print("输入第二个序列的大小:");
54         int B_size=reader.nextInt();
55         System.out.print("输入第二个序列的值:");
56         for(int i=1;i<=B_size;i++){
57             B[i]=reader.nextInt();
58         }
59         System.out.print("最长公共子序列为:");
60         LCSLength(A,B,C,A_size,B_size,b);
61         System.out.println("长度为:"+C[A_size][B_size]);
62         reader.close();
63     }
64 
65 }

10:34:09

2018-10-28

原文地址:https://www.cnblogs.com/chiweiming/p/9864769.html