HBU训练营【动态规划DP】——最长公共子序列长度 (15分)

求两个字符串的最长公共子序列长度。

输入格式:
输入长度≤100的两个字符串。

输出格式:
输出两个字符串的最长公共子序列长度。

输入样例1:

ABCBDAB
BDCABA

输出样例1:

4

输入样例2:

ABACDEF
PGHIK

输出样例2:

0

公共子序列:如果两个字符串包含共同的子序列,那么这个子序列就被称为公共子序列了。如样例中的ABCBDAB和BDCABA的公共子序列就有A、BD、BDAB等。而其中最长的子序列就是所谓的最长公共子序列(LCS)。当然,最长公共子序列也许不止一个,题目给的就是一个代表例子,它们的LCS为“BCBA”,“BCAB”,“BDAB”。
没系统学过这些算法思想真是难受,好多都想不到,除非那种明显的,比如斐波那契数列那样的,应该还是这方面做题少的原因。。
假设现在有两个字符串序列:X={x1,x2,…xi…xm},Y={y1,y2,…yj…yn}。如果知道了X={x1,x2,…xi-1}和Y={y1,y2,…yj-1}的最大公共子序列,那么后续的可以按递推的方法进行求解,就像斐波那契数列一样,知道了前两项,就能求后边的一项。如果xi==yj,其长度是len(L)+1。即序列{Xi,Yj}的最优解是由{xi-1,yj-1}求得的。如果不相等,则是前边所求的,{xi,yj-1}和{xi-1,yj}中的最大值,总之都是根据前边已知的解去求解未知的解,下边两种方式都可以,无非开始的编号不同
#include <iostream>
#include <string>
using namespace std;

int arr[105][105],len1,len2;
string s1,s2;

void DP(){
	for(int i = 1;i<=len1;i++){
		for(int j = 1;j<=len2;j++){
			if(s1[i-1]==s2[j-1])
				arr[i][j] = arr[i-1][j-1] + 1;
			else
				arr[i][j] = max(arr[i][j-1],arr[i-1][j]); 
		}
	}
}

int main(){
	getline(cin,s1);
	getline(cin,s2);
	len1 = s1.length();
	len2 = s2.length();
	DP();
	cout << arr[len1][len2];
	return 0;
} 
#include <iostream>
#include <string>
using namespace std;

int arr[105][105],len1,len2;
string s1,s2;

void DP(){
	for(int i = 0;i<len1;i++){
		for(int j = 0;j<len2;j++){
			if(s1[i]==s2[j])
				arr[i+1][j+1] = arr[i][j] + 1;
			else
				arr[i+1][j+1] = max(arr[i][j+1],arr[i+1][j]); 
		}
	}
}

int main(){
	//防止输入的字符串有空格
	getline(cin,s1);
	getline(cin,s2);
	len1 = s1.length();
	len2 = s2.length();
	DP();
	cout << arr[len1][len2];
	return 0;
} 
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值