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;
} 

猜你喜欢

转载自blog.csdn.net/weixin_45845039/article/details/107923840