【算法】动态规划解决最长公共子串--画图详解
题目:若给定序列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的公共子序列。
给定2个序列X={x1,x2,…,xm}和Y={y1,y2,…,yn},找出X和Y的最长公共子序列。
步骤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 |
测试截图:
本文来自博客园,作者:小李不背锅,转载请注明原文链接:https://www.cnblogs.com/lishilin-glut/p/15436908.html