第九章 動態規劃-1265 【例9.9】最長公共子序列

1265:【例9.9】最長公共子序列

時間限制: 1000 ms 內存限制: 65536 KB
提交數: 6432 通過數: 3356
【題目描述】
一個給定序列的子序列是在該序列中刪去若干元素後得到的序列。確切地說,若給定序列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的一個最長公共子序列。

【輸入】
共有兩行。每行爲一個由大寫字母構成的長度不超過1000的字符串,表示序列X和Y。

【輸出】
第一行爲一個非負整數。表示所求得的最長公共子序列的長度。若不存在公共子序列.則輸出文件僅有一行輸出一個整數0。

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


確定狀態轉移方程和邊界:
三種情況來考慮:

s1[ i ]不在公共子序列中,該情況下f[ i ][j ] =f [ i-1 ][ j ];
s2[i ]不在公共子序列中;f[i][j]=f[i][j-1];
s1[i]=s2[j],s1[i] 與s2[j]在公共子序列中,該情況下f[i][j]=f[i-1][j-1]+1;
*f[i][j]取上述三個中的max
————————————————

#include<cstdio>
#include<cstring>
#include<iostream>
const int N = 1000;
using namespace std;
string s1,s2;
int lena, lenb;
int f[N][N];
int main(){
	cin >> s1;
	cin >> s2;
	lena = s1.size();
	lenb = s2.size();
	for(int i = 1; i <= lena ; i++)
	  for(int j = 1; j <= lenb; j++)
	   {
	   	if(s1[i-1] == s2[j-1])
	   	 f[i][j] = max(f[i][j],f[i-1][j-1] + 1);
	   	 else
	   	 f[i][j] = max(f[i][j-1],f[i-1][j]);
	   }
	printf("%d\n",f[lena][lenb]);
	return 0;
}

 
int LCS()//dp核心代碼
{
   dp[0][0]=0
   for(int i = 1 ; i < = lena ; i++)
    for(int j = 1 ; j <= lenb ; j+++)
     	if(s1[i] == s2[j])
		dp[i][j] = dp[i-1][j-1]+1;
	else
	dp[i][j] = max(dp[i-1][j] , dp[i][j-1]);
   return dp[lena][lenb];
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章