动态规划概念:
动态规划
算法
通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。我们可以用一个表来记录所有已解的子问题的答案。不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。这就是动态规划法的基本思路。
问题:最长公共序列数
给定两个字符串A和B,返回两个字符串的最长公共子序列的长度。例如,A="1A2C3D4B56”,B="B1D23CA45B6A”,”123456"或者"12C4B6"都是最长公共子序列。
给定两个字符串A和B,同时给定两个串的长度n和m,请返回最长公共子序列的长度。保证两串长度均小于等于300。
测试样例: "1A2C3D4B56",10,"B1D23CA45B6A",12
返回:6
分析:
设dp[n][m] ,为A的前n个字符与B的前m个字符的公共序列长度。
假如A的最后一个元素 与 B的最后一个元素相等,那么A和B的LCS就等于 {A减去最后一个元素} 与 {B减去最后一个元素} 的 LCS 再加上 A和B相等的最后一个元素。(当A[n]==B[m]的时候,dp[i][j] = max(dp[i-1][j-1]+1,dp[i-1][j],dp[i][j-1]))
假如A的最后一个元素 与 B的最后一个元素不等(本例子就是属于这种情况),那么A和B的LCS就等于 : {A减去最后一个元素} 与 B 的LCS, {B减去最后一个元素} 与 A 的LCS 中的最大的那个序列。(当A[n]!=B[m]的时候,dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]))
代码:
- public class LCS {
- public int findLCS(String A, int n, String B, int m) {
- // write code here
- int[][] dp = new int[n][m];
- char[] a = A.toCharArray();
- char[] b = B.toCharArray();
- for(int i=0;i<n;i++){
- if(a[i]==b[0]){
- dp[i][0] = 1;
- for(int j=i+1;j<n;j++){ //灰色部分用于初始化当A或B字符串长度为一的情
- //况(最基本的部分),为后面求长度准备数据。
- dp[j][0] = 1;
- }
- break;
- }
- }
- for(int i=0;i<m;i++){
- if(a[0]==b[i]){
- dp[0][i] = 1;
- for(int j=i+1;j<m;j++){
- dp[0][j] = 1;
- }
- break;
- }
- }
- for(int i=1;i<n;i++){
- for(int j=1;j<m;j++){
- if(a[i]==b[j]){
- dp[i][j] = max(dp[i-1][j-1]+1,dp[i-1][j],dp[i][j-1]);
- }else{
- dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
- }
- }
- }
- return dp[n-1][m-1];
- }
- public int max(int a,int b,int c){
- int max = a;
- if(b>max)
- max=b;
- if(c>max)
- max = c;
- return max;
- }