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

题目:若给定序列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

测试截图:

 


__EOF__

本文作者小李不背锅
本文链接https://www.cnblogs.com/lishilin-glut/p/15436908.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   小李不背锅  阅读(430)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示