动态规划--最长公共子序列

本文介绍了一种求解最长公共子序列问题的算法,并通过Java代码实现了该算法。首先,利用动态规划的方法填充一个二维数组,记录两个字符串之间的最长公共子序列长度;然后,从数组中逆向追踪,构建出具体的最长公共子序列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、填值,递增填
·长度分别为m=len1+1和n=len2+1;
·创建1个二维数组L[m.n];
·初始化L数组内容为0
· i和j分别从1开始,i++,j++循环:
- 如果str1[i] == str2[j],则L[i,j] = L[i - 1, j -1] + 1;
- 如果str1[i] != str2[j],则L[i,j] = max{L[i,j - 1],L[i - 1, j]}
·最后从L[i,j]中的数字一定是最大的,且这个数字就是最长公共子序列的长度
·从数组L中找出一个最长的公共子序列

2、返回路线,从数组L中查找一个最长的公共子序列

.i和j分别从m-1,n-1开始,递减循环直到i = 1,j = 1。其中,m和n分别为两个串的长度。
·如果str1[i] == str2[j],则将str[i]字符插入到子序列内,i--,j--;

·如果str1[i] != str[j],则比较L[i,j-1]与L[i-1,j],L[i,j-1]大,则j--,否则i--;(如果相等,则任选一个)

                                        

import java.util.ArrayList;


public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		 String str1 = "ABCBDAB";
		 String str2 = "BDCABA";
		 System.out.println(getLongestCommonSubSquence(str1,str2));
	}
     public static String getLongestCommonSubSquence(String s1,String s2){
    	  int length1=s1.length();
    	  int length2=s2.length();
    	  int m=length1+1;
    	  int n=length2+1;
    	  int[][] L=new int[m][n]; //初始化一个(length1+1)*(length2+1)的二维数组
    	  for(int i=0;i<m;i++){
    		  for(int j=0;j<n;j++){
        		  L[i][j]=0;
        	  }
    	  }
    	  /*第一步填值  s1[i]和s2[j]比较确定L[i][j]
    	   * 相等:对角线+1
    	   * 不等:两边最大值
    	   * */
    	   for(int i=1;i<m;i++){
    		  for(int j=1;j<n;j++){
        		  if(s1.charAt(i-1)==s2.charAt(j-1)){
        			  L[i][j]=L[i-1][j-1]+1;//相等:对角线+1
        		  }
        		  else {//不等:两边最大值
        			  L[i][j]=L[i][j-1]>L[i-1][j]?L[i][j-1]:L[i-1][j];
				  }
        	  }
    	   }
    	   /*第二步,取返回值,s1[i]和s2[j]比较
    	    * 相等:走对角线,i--,j--,保存s1[i]或s2[j]
    	    * 不等:走两边值大的,比较L[i-1][j]和L[i][j-1],若L[i][j-1]大,j--,
    	    * */
    	   StringBuffer sb=new StringBuffer();
    	   for(int i=m-1,j=n-1;i>=1&&j>=1;){
     		    if(s1.charAt(i-1)==s2.charAt(j-1)){
     		    	sb.append(s1.charAt(i-1));//倒序打印的
     		    	i--;
     		    	j--;
     		    }
     		    else{
     		    	if(L[i][j-1]>L[i-1][j]){
     		    		j--;
     		    	}
     		    	else {
						i--;
					}
     		    }
    	   }
    	   sb.reverse();//反转就变成正序了
    	   return sb.toString();//正序打印的
     }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值