动态规划(dp)----公共子序列(LCS) 问题初级理解

动态规划(dp)----公共子序列(LCS) 问题

推理过程
记:
xi x序列的前i个字符(前缀)
yj y序列的前j个字符(前缀)
假设z是LCS(x,y)c++

xm=yn(最后一个字符相同),则不难用反证法证实:
该字符必须是x与y的任一最长公共子序列z(设长度为k)
的最后一个字符,即zk=xm=yn 且显然有zk-1∈LCS(xm-1,yn-1)
即z的前缀zk-1是xm-1与yn-1的最长公共子序列。此时,问题转归于求
xm-1与yn-1的LCS(x,y)的长度即等于LCS(xm-1,yn-1)的长度+1;数组

若xm≠yn,则以不难用反证法证实:要么z∈LCS(xm-1,y),要么z∈LCS(x,yn-1).
因为zk≠xm,zk≠yn其中至少有一个必成立,若zk≠xm则有z∈LCS(xm-1,y)
,相似的,若zk≠yn则有z∈LCS(x,yn-1),此时,问题划归于求xm-1与y的LCS
及x与yn-1的LCS。LCS(x,y)的长度为:max(LCS(xm-1,y),LCS(想,yn-1))
的长度spa

由与上述当xm≠yn的状况时,求LCS(xm-1,y)的长度与LCS(x,yn-1)的长度
这两个问题是不相互独立
二者都须要求LCS(xm-1,yn-1)的长度。另外两个序列的LCS包含了两个序列
前缀的LCS,故问题具备最优子结构考虑用动态规划code

也就是说,解决这个问题,需求:
1:LCS(xm-1,yn-1)+1;
2: LCS(xm-1,y),LCS(x,yn-1)
3:max(LCS(xm-1,y),LCS(x,yn-1))blog

咱们定义c[i,j]表示xi和yi的LCS的长度
若是i=0或j=0,即一个序列长度为0,那么LCS为0;
根据LCS问题的最优子结构性质,可获得以下公式:递归


                            0                                若i=0或j=0;
                 c[i,j]=c[i-1,j-1]+1                    若i,j>0&&xi=yi
                 max(c[i-1,j],c[i,j-1])                若i,j>0&&xi≠yiip

上述公式是递归思想,可是实际作题中,由于时间限制,一般不会采用递归,2^n,太阔怕啦,常以牺牲空间的方式(记忆化)来增速!
----本身理解是递归是从下到上,而dp数组是从上到下 ,有点斐波那契数列的味道,理解有误的话,还请留言等方式指正!
下面一个最简单的应用吧,hdu 1159题
 

 hdu 1159

Problem Description
A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = <x1, x2, ..., xm> another sequence Z = <z1, z2, ..., zk> is a subsequence of X if there exists a strictly increasing sequence <i1, i2, ..., ik> of indices of X such that for all j = 1,2,...,k, xij = zj. For example, Z = <a, b, f, c> is a subsequence of X = <a, b, c, f, b, c> with index sequence <1, 2, 4, 6>. Given two sequences X and Y the problem is to find the length of the maximum-length common subsequence of X and Y. 
The program input is from a text file. Each data set in the file contains two strings representing the given sequences. The sequences are separated by any number of white spaces. The input data are correct. For each set of data the program prints on the standard output the length of the maximum-length common subsequence from the beginning of a separate line. 
 

Sample Input
abcfbc abfcab programming contest abcd mnp
 

Sample Output
4 2 0
 
注意scanf输入时必定要判断EOF,不然就会超时
 1 #include <bits/stdc++.h>
 2 #include <stdio.h>
 3 #define maxn 1005
 4 #include <string>
 5 #include <algorithm>
 6 
 7 int dp[maxn][maxn]={0};
 8 using namespace std;
 9 
10 int comm_subsequence(char *a,char *b,int len1,int len2){
11      for(int i=1;i<=len1;i++){
12         for(int j=1;j<=len2;j++){
13             if(a[i-1]==b[j-1]){
14                 dp[i][j]=dp[i-1][j-1]+1;
15             }else{
16                 dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
17             }
18         }
19     }
20 
21     return dp[len1][len2];
22 }
23 
24 int  main(){
25     char a[maxn];
26     char b[maxn];
27     while(scanf("%s %s",a,b)!=EOF){
28     int len1=strlen(a);
29     int len2=strlen(b);
30     memset(dp,0,sizeof(dp));
31     int tmp=comm_subsequence(a,b,len1,len2);
32     printf("%d\n",tmp);
33     }
34     return 0;
35 }
相关文章
相关标签/搜索