动态规划_最大公共子序列长度问题

本文通过实例解析动态规划方法求解两个字符串的最大公共子序列长度,并深入讨论动态规划的核心思想及其应用,包括子问题的选择、子问题解的缓存与复用等关键概念。

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

        昨晚部门出去吃火锅,十来个人有说有笑的,感觉很不错,不过因此昨天的"每日一题"也就没时间了,现在补上。

问题:有两个字符串A=a1 a2 a3 ... an和B=b1 b2 b3 ... bm,求两者的最大公共子序列的长度,这里的公共子序列就是相同的两个字符串中字符相同的子序列。如:abcdefgacghlm的最大公共子序列是acg。

        图表分析:

        代码:

package com.wly.algorithmbase.dailyproblem;

/**
 * 动态规划,最大公共子序列长度问题
 * L[i,j] = 0;(i=0或j=0);
 * L[i,j] = L[i-1,j-1]+1;(ai=bj)  
 * L[i,j] = max{L[i,j-1],L[i-1,j]}(ai!=bj)
 * @author wly
 *
 */
public class MaxCommonSubSequenceProblem {

	public static void main(String args[]) {
		String s1 = " " + "CDAFGCU"; //在字符串开头添加"0",因为当ai=bj时,result[i][j] = result[i-1][j-1]+1;
		String s2 = " " + "ACDEFGC";
		
		System.out.println(s1 + "和" + s2 + "的最大子序列长度是:" + solve(s1,s2));
	}
	
	
	public static int solve(String s1,String s2) {

		char[] c1 = s1.toCharArray();
		char[] c2 = s2.toCharArray();
		int[][] result = new int[c1.length][c2.length];

		for(int i=0;i<c1.length;i++) {
			result[i][0] = 0;
		}
		
		for(int j=0;j<c2.length;j++) {
			result[0][j] = 0;
		}
			
		for(int i=1;i<c1.length;i++) {
			for(int j=1;j<c2.length;j++) {
				if(c1[i] == c2[j]) {
					result[i][j] = result[i-1][j-1] + 1;
				} else {
					result[i][j] = Math.max(result[i-1][j], result[i][j-1]);
				}
			}
		}
		
		for(int i=0;i<result.length;i++) {
			for(int j=0;j<result[0].length;j++) {
				System.out.print(result[i][j] + " ");
			}
			System.out.println();
		}
		System.out.println();
		return result[c1.length-1][c2.length-1];
	}
}

        运行结果:

0 0 0 0 0 0 0 0 
0 0 1 1 1 1 1 1 
0 0 1 2 2 2 2 2 
0 1 1 2 2 2 2 2 
0 1 1 2 2 3 3 3 
0 1 1 2 2 3 4 4 
0 1 2 2 2 3 4 5 
0 1 2 2 2 3 4 5 

 CDAFGCU和 ACDEFGC的最大子序列长度是:5

       下面来聊聊本人对动态规划的一点浅显的想法,权当抛砖引玉只用,高手莫喷。在动态规划问题中有:

       1、这一次的选择将影响下一次的选择。比如01背包问题中可能因为这一次放了一个很大的物体,导致了下一个物体没有足够的空间放置。那么到底放还是不放下一个物体,代表了两个解,取更优解存储。

       2、将本次之前的"所有可能成为全局最优解的子问题解"缓存起来。下一阶段的选择就是基于当前阶段缓存起来的最优子问题解集合的。然后将本阶段缓存起来的最优子问题解和下一阶段的所有解元素合成,得到下一阶段的最优子问题解的缓存,如此迭代,直到得到全局最优解。如此便保证了当前阶段缓存起来的解结合都是可能成为全局最优解的解。同时全局最优解必定包含这些解中的一个。直到最后一个子阶段,从中选出最优解,该最优解即是全局最优解。

       3、动态规划的核心就是子问题解的缓存及复用,从而减少算法的计算量。

       4、需要注意的设计合适的子问题分解方式是一个"创造性"过程。这里的子问题分解方式其实就是所谓的状态转移方程了,寻找这个状态转移方程的过程是一个创造性的过程。

原来用脑袋想起来很复杂的问题,用状态转移公式解起来这么简单。但是需要学习的能力就是推导状态转移公式的能力,这就好透彻的理解动态规划的思想了。理解动态规划中"解集合的缓存"及复用。

        O啦~~~

        转载请保留出处:http://blog.youkuaiyun.com/u011638883/article/details/14519965

        谢谢!!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值