動態規劃(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 }
相關文章
相關標籤/搜索