动态规划---最长的公共子序列java版本

package com.duoduo.test1;
/**
	 * 给定两个序列X={ x1,x2,.....xm}  Y={y1,y2///yn} 找出两者的一个最长的公共子序列z
	 * 采用动态规划的思想
	 *  1 分析最优解的结构特征 假设已经知道了最优解
	 *  2 建立最优解的递归式  
	 *  3 自底向上求解最优值 并记录最优值和最优策略
	 *  4 构造最优解
	 *  
	 *  算法设计: 确定合适的数据结构---》初始化--》循环得到最长长度--》递推来源得到最优解
	 */
import java.util.Scanner;
public class Test4_2 {
	//已知两个字符串  求解公共最长子序列
	static String s1;
	static String s2;
	
	public static void main(String [] args) {
		Scanner sc=new Scanner(System.in);
		System.out.print("输入第一个字符串S1:");
	    s1= sc.next();
		System.out.print("输入第二个字符串S2:");
		s2=sc.next();
		
		int len1=s1.length();                //计算两个字符串的长度
		int len2=s2.length();
		
		int [][] c=new int[len1+1][len2+1];  //记录最长公共子序列长度 
		int [][] b=new int[len1+1][len2+1];  //记录最长子序列的来源
		
		/*初始化    第一行第一列均初始化为0*/
		for(int i=0;i<=len1;i++)
			c[i][0]=0;
		for(int j=0;j<=len2;j++)
			c[0][j]=0;
		
		LCSL(c,b);                          //求解最长公共子序列  
		System.out.println("S1 和S2的最长公共子序列长度为 :"+c[len1][len2]);
		System.out.println("S1 和S2的最长公共子序列为 :");
		print(b,len1,len2);                //递归构造最长公共子序列
	
	}
	
	/*求解最长公共子序列  */
	public static void LCSL(int [][] c,int[][] b) {
		int i,j;
		//循环遍历字符串S1 和S2  比较两者是否相等  
		for( i=1; i<=s1.length();i++) {      
			for(j=1;j<=s2.length();j++) {
				if(s1.charAt(i-1)==s2.charAt(j-1)) {  //字符下标从0开始
					//若当前字符相等 则公共子序列长度=该字符前的最长公共子序列+1
					c[i][j]=c[i-1][j-1]+1;            
					b[i][j]=1;         
				}else {
					if(c[i][j-1]>=c[i-1][j]) {       //不等 找出两者最大值  相等默认取左值
						c[i][j]=c[i][j-1];           //取左值
						b[i][j]=2;
					}else {
						c[i][j]=c[i-1][j];           //取上面值
						b[i][j]=3;
					}
				}
			}
		}
	}
	/*递归构造最长公共子序列最优解*/
	public static void print(int[][] b,int i,int j) {   
		if(i==0 || j==0) 
			return;        //若有其中之一为0 则停止 (递归结束条件)
		if(b[i][j]==1) {    //若来源为1 则递归左上角
			print(b,i-1,j-1);
			System.out.print(s1.charAt(i-1));  //并打印此值
		}else if(b[i][j]==2) {
			print(b,i,j-1);                    //来源左侧
		}else {
			print(b,i-1,j);                    //来源上面
		}
	}
}

结果验证:

动态规划---最长的公共子序列java版本_第1张图片

动态规划---最长的公共子序列java版本_第2张图片


算法解析及优化:

时间复杂度:每个数组单元的计算耗费O(1)时间,如果两个字符串的长度分别是m, n,那么算法时间复杂度O(m*n)

空间复杂度:两个二维数组 c[][] ,b[][],占用的空间 O(m*n).

算法优化: 直接用c[i][j] 来判断来源于哪个值,从而不用b[][], 这样可以节省O(m*n)数量级仍然没有变化

你可能感兴趣的:(左.算法,/,趣学算法,动态规划)