1. 程式人生 > >【例9.9】最長公共子序列

【例9.9】最長公共子序列

std 不存在 cst i++ 公共子串 ostream ont enter http

【例9.9】最長公共子序列

鏈接:http://ybt.ssoier.cn:8088/problem_show.php?pid=1265


時間限制: 1000 ms 內存限制: 65536 KB

【題目描述】

一個給定序列的子序列是在該序列中刪去若幹元素後得到的序列。確切地說,若給定序列X=<x1,x2,…,xm>,則另一序列Z=<z1,z2,…,zk>是X的子序列是指存在一個嚴格遞增的下標序列<i1,i2,…,ik>,使得對於所有j=1,2,…,k有:

Xij=Zj

例如,序列Z=<B,C,D,B>是序列X=<A,B,C,B,D,A,B>的子序列,相應的遞增下標序列為<2,3,5,7>。給定兩個序列X和Y,當另一序列Z既是X的子序列又是Y的子序列時,稱Z是序列X和Y的公共子序列。例如,若X=<A,B,C,B,D,A,B>和Y=<B,D,C,A,B,A>,則序列<B,C,A>是X和Y的一個公共子序列,序列 <B,C,B,A>也是X和Y的一個公共子序列。而且,後者是X和Y的一個最長公共子序列.因為X和Y沒有長度大於4的公共子序列。

給定兩個序列X=<x1,x2,…,xm>和Y=<y1,y2….yn>.要求找出X和Y的一個最長公共子序列。

【輸入】

共有兩行。每行為一個由大寫字母構成的長度不超過200的字符串,表示序列X和Y。

【輸出】

第一行為一個非負整數。表示所求得的最長公共子序列的長度。若不存在公共子序列.則輸出文件僅有一行輸出一個整數0。否則在輸出文件的第二行輸出所求得的最長公共子序列(也用一個大寫字母組成的字符串表示)。若符合條件的最長公共子序列不止一個,只需輸出其中任意一個。

【輸入樣例】

ABCBDAB
BDCABA

【輸出樣例】

4

【提示】

最長公共子串(Longest Common Substirng)和最長公共子序列(Longest Common Subsequence,LCS)的區別為:子串是串的一個連續的部分,子序列則是從不改變序列的順序,而從序列中去掉任意的元素而獲得新的序列;也就是說,子串中字符的位置必須是連續的,子序列則可以不必連續。字符串長度小於等於1000。

題解:

序列str1和序列str2 ·長度分別為m和n; ·創建1個二維數組L[m.n]; ·初始化L數組內容為0 ·m和n分別從0開始,m++,n++循環: - 如果str1[m] == str2[n],則L[m,n] = L[m - 1, n -1] + 1; - 如果str1[m] != str2[n],則L[m,n] = max{L[m,n - 1],L[m - 1, n]} ·最後從L[m,n]中的數字一定是最大的,且這個數字就是最長公共子序列的長度 ·從數組L中找出一個最長的公共子序列
#include<iostream>
#include
<cstdio> #include<cstring> using namespace std; int f[205][205]; string s1,s2; int main() { int ans=0; cin>>s1>>s2; int len1=s1.size(),len2=s2.size(); for(int i=0;i<=len1;i++)f[i][0]=0; for(int i=0;i<=len2;i++)f[0][i]=0; for(int i=1;i<=len1;i++) for(int j=1;j<=len2;j++) { f[i][j]=max(f[i-1][j],f[i][j-1]); if(s1[i-1]==s2[j-1]) f[i][j]=max(f[i][j],f[i-1][j-1]+1); } cout<<f[len1][len2]<<endl; }

【例9.9】最長公共子序列