【算法】动态规划解决最长公共子串--画图详解

题目:若给定序列X={x1,x2,,xm},则另一序列Z={z1,z2,,zk},是X的子序列是指存在一个严格递增下标序列{i1,i2,,ik}使得对于所有j=1,2,,k有:zj=xij。例如,序列Z={BCDB}是序列X={ABCBDAB}的子序列,相应的递增下标序列为{2357}

给定2个序列XY,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列XY的公共子序列。

给定2个序列X={x1,x2,,xm}Y={y1,y2,,yn},找出XY的最长公共子序列。

步骤1:先用一个二维数组作为记录表,记录子串的长度。代码如下:

 1 static void  LCSLength (String x,String y,int b[][])
 2     {
 3         int m,n,i,j;
 4         m=x.length()-1;
 5         n=y.length()-1;
 6 
 7         int [][]c=new int[m+1][n+1];
 8         for (i = 1; i <= m; i++) c[i][0] = 0;
 9         for (i = 1; i <= n; i++) c[0][i] = 0;
10         for (i = 1; i <= m; i++)
11             for (j = 1; j<= n; j++)
12             {
13                 if (x.charAt(i)==y.charAt(j))//(x[i]==y[j])
14                 {
15                     c[i][j]=c[i-1][j-1]+1;
16                     b[i][j]=1;
17                 }
18                 else if (c[i-1][j]>=c[i][j-1])
19                 {
20                     c[i][j]=c[i-1][j];
21                     b[i][j]=2;
22                 }
23                 else
24                 {
25                     c[i][j]=c[i][j-1];
26                     b[i][j]=3;
27                 }
28             }
29     }

计算公共字串的最长长度并记录三种情况的坐标到b数组里面,后面的LCS用到。

表格讲解:i = 1到8,j =1到8.

图解如下:(建议边看代码边跟着图解来,用WPS画的图,将就一下)

 递归输出最长字串:

 1 static void LCS(int i,int j, String x,int b[][])
 2     {
 3         if (i ==0 || j==0) return;
 4         if (b[i][j]== 1)
 5         {
 6             LCS(i-1,j-1,x,b);
 7             System.out.print(x.charAt(i)+" ");
 8         }
 9         else if (b[i][j]== 2)
10             LCS(i-1,j,x,b);
11         else
12             LCS(i,j-1,x,b);
13     }

图解如下:

建议仔细琢磨,最后给出完整代码:

 1 //最长公共子序列 SubString.java
 2 import java.util.Scanner;
 3 
 4 public  class SubString {
 5     static void  LCSLength (String x,String y,int b[][])
 6     {
 7         int m,n,i,j;
 8         m=x.length()-1;
 9         n=y.length()-1;
10 
11         int [][]c=new int[m+1][n+1];
12         for (i = 1; i <= m; i++) c[i][0] = 0;
13         for (i = 1; i <= n; i++) c[0][i] = 0;
14         for (i = 1; i <= m; i++)
15             for (j = 1; j<= n; j++)
16             {
17                 if (x.charAt(i)==y.charAt(j))//(x[i]==y[j])
18                 {
19                     c[i][j]=c[i-1][j-1]+1;
20                     b[i][j]=1;
21                 }
22                 else if (c[i-1][j]>=c[i][j-1])
23                 {
24                     c[i][j]=c[i-1][j];
25                     b[i][j]=2;
26                 }
27                 else
28                 {
29                     c[i][j]=c[i][j-1];
30                     b[i][j]=3;
31                 }
32             }
33     }
34 
35     static void LCS(int i,int j, String x,int b[][])
36     {
37         if (i ==0 || j==0) return;
38         if (b[i][j]== 1)
39         {
40             LCS(i-1,j-1,x,b);
41             System.out.print(x.charAt(i)+" ");
42         }
43         else if (b[i][j]== 2)
44             LCS(i-1,j,x,b);
45         else
46             LCS(i,j-1,x,b);
47     }
48 
49     public static void main(String[] args) {
50         String x,y;
51         Scanner scan=new Scanner(System.in);
52         System.out.println("input two strings:");
53         x=scan.next();
54         y=scan.next();
55         x=" "+x;
56         y=" "+y;
57         int[][] b=new int[x.length()+1][y.length()+1];
58         LCSLength(x,y,b);
59         System.out.println("The result is:");
60         LCS(x.length()-1, y.length()-1, x, b);
61     }
62 }

(1)测试数据1

aghhenebgv

结果

gaheighje

a g h e

测试截图1:

2)测试数据2

abbbanbgjljj

结果

accabnjjgljj

a b n g l j j

测试截图2:

(3)测试数据3

httpswwwlishiln

结果

tttpwwwhalishilin

t t p w w w l i s h i l n

测试截图:

 

posted @ 2021-10-22 00:12  小李不背锅  阅读(399)  评论(0编辑  收藏  举报