動態規划1--最長公共子序列


動態規划1--最長公共子序列

一、動態規划

經常會遇到復雜問題不能簡單地分解成幾個子問題,而會分解出一系列的子問題。簡單地采用把大問題分解成子問題,並
綜合子問題的解導出大問題的解的方法,問題求解耗時會按問題規模呈冪級數增加。

為了節約重復求相同子問題的時間,引入一個數組,不管它們是否對最終解有用,把所有子問題的解存於該數組中,這就
是動態規划法所采用的基本方法。

二、心得

遞推公式的推導

遞推公式的證明方法

代碼的寫法:把遞推公式直接寫進代碼即可

 

三、題目

給出兩個字符串,求出這樣的一個最長的公共子序列的長度:子序列中的每個字符都能在兩個原串中找到,而且每個字符的先后順序和原串中的先后順序一致。

Sample Input:樣例輸入

abcfbc abfcab

programming contest

abcd mnp

Sample Output:樣例輸出

4
2
0

 

四、分析

 

 

2、證明
S1[i-1]!= s2[j-1]時,MaxLen(S1,S2)不會比MaxLen(S1,S2j-1)
和MaxLen(S1i-1,S2)兩者之中任何一個小,也不會比兩者都大。
(1)不比任何一個小:MaxLen(S1,S2)字符串長於后兩者
(2)也不會比兩者都大:反證法,假設比兩者都大:

若MaxLen(S1,S2)比MaxLen(S1,S2j-1)大,說明S2(j)這個字符與S1中的字符相等,並且S2(j)和這個相等的字符是最長公共子序列的最后一個。

若MaxLen(S1,S2)比MaxLen(S1i-1,S2)大,說明S1(i)這個字符與S2中的字符相等,並且S1(i)和這個相等的字符是最長公共子序列的最后一個。

上面兩種情況都是最長公共子序列的最后一個,而這個最長公共子序列是MaxLen(S1,S2)的最長公共子序列,所以最后一個要相等。

那會得出S1[i]== s2[j]的結論,與假設沖突。

 

五、代碼及結果

 1 /*
 2 最長公共子序列 
 3 1、遞推公式:
 4 (分最后一個相同和最后一個不同來分析) 
 5 當i或j等於0,MaxLen(i,j)==0;
 6 當s1和s2的最后一個字符相同時,MaxLen(i,j)=MaxLen(i-1,j-1)+1;
 7 當s1和s2的最后一個字符不同時,MaxLen(i,j) = Max(MaxLen(i,j-1),MaxLen(i-1,j) ); 
 8 2、證明 
 9 S1[i-1]!= s2[j-1]時,MaxLen(S1,S2)不會比MaxLen(S1,S2j-1)
10 和MaxLen(S1i-1,S2)兩者之中任何一個小,也不會比兩者都大。
11 (1)不比任何一個小:MaxLen(S1,S2)字符串長於后兩者
12 (2)也不會比兩者都大:反證法,假設比兩者都大,那會得出S1[i-1]== s2[j-1]的結論,與假設沖突 
13 3、代碼
14 直接寫遞推公式就好了 
15 */
16 /*
17 錯誤一:結果不對
18 for(j=1;j<=length2;j++),漏了等號,所以都沒執行到這來,所以結果不對 
19 */
20 #include <iostream>
21 #include <cstring> 
22 using namespace std;
23 char sz1[1000];//字符數組1 
24 char sz2[1000];//字符數組2 
25 int maxLen[1000][1000];
26 //MaxLen(i,j)表示s1的左邊i個字符形成的子串,
27 //與s2左邊的j個字符形成的子串的最長公共子序列的長度(i,j從0開始算) 
28 int main(){
29     freopen("in.txt","r",stdin); 
30     while(cin>>sz1>>sz2){
31         int length1=strlen(sz1);//求字符數組1的長度 
32         int length2=strlen(sz2);//求字符數組2的長度
33         int nTmp;
34         int i,j;
35         //初始化邊界情況 
36         for(i=0;i<=length1;i++)
37             maxLen[i][0]=0;
38         for(j=0;j<=length2;j++)
39             maxLen[0][j]=0; 
40         //動態規划求解最長公共子序列  
41         for(i=1;i<=length1;i++){
42             for(j=1;j<=length2;j++){
43                 if(sz1[i-1]==sz2[j-1]){//字符數組從0開始存數據的 
44                     //當s1和s2的最后一個字符相同時,MaxLen(i,j)=MaxLen(i-1,j-1)+1; 
45                     maxLen[i][j]=maxLen[i-1][j-1]+1;
46                 }    
47                 else{
48                     //當s1和s2的最后一個字符不同時,MaxLen(i,j) = Max(MaxLen(i,j-1),MaxLen(i-1,j) );  
49                      maxLen[i][j]=max(maxLen[i][j-1],maxLen[i-1][j]);
50                 }
51             } 
52                         
53         }
54         /*
55         for(i=1;i<=length1;i++){
56             for(j=1;j<=length2;j++){
57                 cout<<maxLen[i][j]<<" ";
58             }
59             cout<<endl;
60         }
61         */ 
62         //cout<<length1<<" "<<length2<<endl;
63         cout<<maxLen[length1][length2]<<endl;
64     }
65     return 0;
66 } 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM