【動態規劃】NYOJ最長公共子序列
阿新 • • 發佈:2019-02-17
最長公共子序列
時間限制:3000 ms | 記憶體限制:65535 KB 難度:3- 描述
- 咱們就不拐彎抹角了,如題,需要你做的就是寫一個程式,得出最長公共子序列。
tip:最長公共子序列也稱作最長公共子串(不要求連續),英文縮寫為LCS(Longest Common Subsequence)。其定義是,一個序列 S ,如果分別是兩個或多個已知序列的子序列,且是所有符合此條件序列中最長的,則 S 稱為已知序列的最長公共子序列。- 輸入
- 第一行給出一個整數N(0<N<100)表示待測資料組數
接下來每組資料兩行,分別為待測的兩組字串。每個字串長度不大於1000. - 輸出
- 每組測試資料輸出一個整數,表示最長公共子序列長度。每組結果佔一行。
- 樣例輸入
-
2 asdf adfsd 123abc abc123abc
- 樣例輸出
-
3 6
思路如下:
題目一開始不會,因為DP都沒怎麼學過,做這道題就是為了學習的,還是看了別人的一些解釋才算是寫出來程式碼了。
其實思路很簡單:
首先,定義個dp[i][j]表示字串S1的第i個字元(包括i)以前的所有字元 和 字串S2的第j個字元以前的(包括j)所有字元 之間最大的公共子序列的長度。
其次,可以列出來DP公式:dp[i][j]=dp[i-1][j]+dp[i][j-1]
然後,設定兩個for迴圈對字串S1和字串S2遍歷,並設定一個標記sum=0。當s1[i-1]==s2[j-1](即s1的第i個字元和s2的第j個字元相同),則讓dp[i][j]=dp[i][j]+1。如果不相等的話,此時需要找s1的第i個字元內和s2的第j個字元內的最長串:sum=dp[i][j]。
最後,迴圈結束,輸出sum。
#include <iostream> #include <string.h> using namespace std; char s1[1005],s2[1005]; int dp[1005][1005]; int max(int a,int b) { return a>b?a:b; } int main() { int t; int len1,len2; int i,j; cin>>t; while(t--) { cin>>s1>>s2; len1=strlen(s1); len2=strlen(s2); memset(dp,0,1005*1005); int sum=0; for(i=1;i<=len1;i++) //雙層for迴圈遍歷兩個陣列 { for(j=1;j<=len2;j++) { if(s1[i-1]==s2[j-1]) //如果相等,則令最大串長度加1 { dp[i][j]=dp[i-1][j-1]+1; } else //如果不相等,求出此時的s1的i個字元內和s2的j個字元內的最大串長度 dp[i][j]=max(dp[i-1][j],dp[i][j-1]); if(sum<dp[i][j]) sum=dp[i][j]; } } cout<<sum<<endl; } return 0; }