首页 > 编程语言 >【c++】【算法】【动态规划】最长公共子序列

【c++】【算法】【动态规划】最长公共子序列

时间:2025-01-17 13:28:05浏览次数:3  
标签:string int c++ dest 算法 vector vec 序列 dp

【c++】【算法】【动态规划】最长公共子序列

//递归方式
//最长公共子序
//直接递归 求最长公共子序长度
int FindValue(const string& X, const string& Y, int i, int j)
{
	if (i == 0 || j == 0)return 0;
	if (X[i] == Y[j])return FindValue(X, Y, i - 1, j - 1)+1;
	else return std::max(FindValue(X, Y, i, j - 1), FindValue(X, Y, i - 1, j));
}

//动态规划 //递归+表保存 求最长公共子序长度
int FindValue1(const string& X, const string& Y, vector<vector<int>>& vec, int i, int j)
{
	if (i <= 0 || j <= 0)return 0;
	if (vec[i][j] > 0)return vec[i][j];
	else if (X[i] == Y[j])
	{
		vec[i][j] = FindValue1(X, Y, vec, i - 1, j - 1)+1;
	}
	else
	{
		int t1= FindValue1(X, Y, vec, i, j - 1);
		int t2= FindValue1(X, Y, vec, i-1, j);
		
		vec[i][j] = max(t1, t2);
	}
	return vec[i][j];
}
//动态规划 递归+打印出子序列 //求最长公共子序是什么
//不使用路径数组,直接回溯 dp 数组得到 LCS
//通过递归 + 表格计算并回溯 LCS
void printLCS(int i, int j, const string& X, const string& Y, vector<vector<int>>& dp, string& lcs) {
	// 递归终止条件
	if (i <=0 || j <=0) {
		return;
	}

	// 如果当前字符相等,加入 LCS
	if (X[i] == Y[j]) {
		lcs = X[i] + lcs;
		printLCS(i - 1, j - 1, X, Y, dp, lcs);  // 同时回溯
	}
	// 如果字符不相等,向 dp 数组的较大值处回溯
	else {
		if (dp[i - 1][j] >= dp[i][j - 1]) {
			printLCS(i - 1, j, X, Y, dp, lcs);  // 向上回溯
		}
		else {
			printLCS(i, j - 1, X, Y, dp, lcs);  // 向左回溯
		}
	}
}
//使用路径数组
//1 代表行=列 2代表行-1 3代表列-1
int FindValue2(const string& X, const string& Y, vector<vector<int>>& vec, vector<vector<int>>& dest, int i, int j)
{
	if (i <= 0 || j <= 0)return 0;
	if (vec[i][j] >0 )return vec[i][j];//**
	else if (X[i] == Y[j])
	{
		vec[i][j] = FindValue2(X, Y, vec, dest, i - 1, j - 1) + 1;
		dest[i][j] = 1;
	}
	else
	{
		int t1 = FindValue2(X, Y, vec, dest, i - 1, j);
		int t2 = FindValue2(X, Y, vec, dest, i, j - 1);
		if (t1 > t2)
		{
			vec[i][j] = t1;
			dest[i][j] = 2;
		}
		else
		{
			vec[i][j] = t2;
			dest[i][j] = 3;
		}
	}
	return vec[i][j];

}
void Print(vector<vector<int>>& vec)
{
	int n = vec.size();
	for (int i = 1;i < n;i++)
	{
		for (int j = 1;j < vec[i].size();j++)
		{
			cout << vec[i][j] << " ";
		}
		cout << endl;
	}
}
void printPublicSub(vector<vector<int>>& dest, int i, int j,string&X)
{
	if (i <= 0 || j <= 0)return;
	if (dest[i][j] == 1)
	{
		printPublicSub(dest, i - 1, j - 1,X);
		cout << X[i] << " ";
	}
	else if (dest[i][j] == 2)
	{
		printPublicSub(dest, i - 1, j, X);
	}
	else
	{
		printPublicSub(dest, i, j-1, X);
	}
}

//非递归方式 求最长公共子序长度
int FindValue3(const string& X, const string& Y, int m, int n)
{
	vector<vector<int>>dp(m + 1, vector<int>(n + 1, 0));

	for (int i = 1;i <= m;i++)
	{
		for (int j = 1;j <= n;j++)
		{
			if (X[i - 1] == Y[j - 1])
			{
				dp[i][j] = dp[i - 1][j - 1] + 1;
			}
			else
			{
				dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
			}
		}
	}

	return dp[m][n];
}
//非递归方式 求最长公共子序是什么
int FindValue4(const string& X, const string& Y, int m, int n,string &lcs)
{
	vector<vector<int>>dp(m + 1, vector<int>(n + 1, 0));

	for (int i = 1;i <= m;i++)
	{
		for (int j = 1;j <= n;j++)
		{
			if (X[i - 1] == Y[j - 1])
			{
				dp[i][j] = dp[i - 1][j - 1] + 1;
				
			}
			else
			{
				dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
			}
		}
	}
	
	// 从 dp 数组回溯得到 LCS
	int i = m, j = n;
	while (i > 0 && j > 0) {
		if (X[i] == Y[j]) {
			lcs = X[i - 1] + lcs;  // 字符匹配,加入 LCS
			i--;
			j--;
		}
		else if (dp[i - 1][j] > dp[i][j - 1]) {
			i--;  // 向上回溯
		}
		else {
			j--;  // 向左回溯
		}
	}

	return dp[m][n];
}

int main()
{
	string X = "#ABCBDAB";
	string Y = "#BDCABA" ;
	int i = X.size()-1;
	int j = Y.size()-1;
	
	vector<vector<int>>vec1(i + 1, vector<int>(j + 1, 0));
	
	//int n = FindValue1(X, Y, vec1, i, j);
	//cout << n << endl;
	//Print(vec1);
	// 回溯 dp 数组得到具体的 LCS
	//string lcs;
	//printLCS(i, j,X,Y,vec1, lcs);
	//cout << lcs << endl;
	//cout << "---------------------------" << endl;
	//cout << "---------------------------" << endl;
	//vector<vector<int>>vec(i + 1, vector<int>(j + 1, 0));
	//vector<vector<int>>dest(i + 1, vector<int>(j + 1, 0));
	//int m=FindValue2(X, Y, vec,dest,i,j);
	
	//cout << m << endl;
	//cout << "---------------------------" << endl;
	//Print(vec);
	//cout << "---------------------------" << endl;
	//Print(dest);
	//cout << "---------------------------" << endl;
	//printPublicSub(dest, i, j, X);

	//int m = FindValue3(X, Y, i, j);
	//cout << m << endl;

	//string lcs;
	//int m=FindValue4(X, Y, i, j,lcs);
	//cout << m << endl;
	//cout << lcs << endl;


	
}

标签:string,int,c++,dest,算法,vector,vec,序列,dp
From: https://blog.csdn.net/m0_64014551/article/details/145205711

相关文章

  • 解决一下typora不使用序列号也能激活问题。
     1.找到typora的安装目录右击typora图标,点击属性即可看到2.按照Typora路径到—>resources—>page-dist—>static—>js这个路径找到这两个文件LicenseIndex.180dd4c7.xxxxxxx.chunk.jsLicenseIndex.180dd4c7.xxxxxxx.chunk.js 打开这两个文件分别替换Ctrl+F搜索......
  • 【LeetCode】力扣刷题热题100道(31-35题)附源码 搜索二维矩阵 岛屿数量 腐烂的橙子 课程
    一、搜索二维矩阵编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:每行的元素从左到右升序排列。每列的元素从上到下升序排列。可以使用从右上角开始搜索的方法来有效地找到目标值。选择起始位置:从矩阵的右上角开始。......
  • 【华为OD-E卷 - 最大花费金额 100分(python、java、c++、js、c)】
    【华为OD-E卷-最大花费金额100分(python、java、c++、js、c)】题目双十一众多商品进行打折销售,小明想购买自己心仪的一些物品,但由于受购买资金限制,所以他决定从众多心仪商品中购买三件,而且想尽可能的花完资金。现在请你设计一个程序帮助小明计算尽可能花费的最大资金数......
  • 【华为OD-E卷 - 一种字符串压缩表示的解压 100分(python、java、c++、js、c)】
    【华为OD-E卷-一种字符串压缩表示的解压100分(python、java、c++、js、c)】题目有一种简易压缩算法:针对全部由小写英文字母组成的字符串,将其中连续超过两个相同字母的部分压缩为连续个数加该字母,其他部分保持原样不变。例如:字符串“aaabbccccd”经过压缩成为字符串“3ab......
  • C++ lambda函数
    lambda函数是C++11标准新增的语法糖,也称为lambda表达式或匿名函数。lambda函数的特点是:距离近、简洁、高效和功能强大。 语法:​[](constint&no)->void{cout<<"亲爱的"<<no<<"号:我是一个一个aaaa。\n";};代码示例:#include<iostream>#include<vector>#......
  • C++文件操作-随机存取&&缓冲区及流状态
    目录文件操作-随机存取1.fstream类2.文件的位置指针3.随机存取文件操作-缓冲区及流状态1.文件缓冲区2.流状态文件操作-随机存取1.fstream类fstream类既可以读文本/二进制文件,也可以写文本/二进制文件。fstream类的缺省模式是ios::in|ios::out,如果文件不存在,以只......
  • 基于 GEE 的 NDVI 产品逐日和逐月时间序列可视化
    目录1数据介绍1.1MODIS/061/MYD13Q1产品数据1.2MODIS/061/MOD09GA产品数据2完整代码3运行结果1数据介绍1.1MODIS/061/MYD13Q1产品数据数据集:ee.ImageCollection("MODIS/061/MYD13Q1")1.2MODIS/061/MOD09GA产品数据数据集:ee.ImageCol......
  • 插值算法 (含代码)
    插值法的原理1,线性差值法2,拉格朗日插值点3,分段插值(1)分段线性插值(2)分段二次插值4,牛顿插值法5,Hermite插值法6,(重要)分段Hermite插值7,(重要)三次样条插值8,n维数据的插值插值算法:用于在已知数据点的基础上,估算出这些数据点之间其他位置的数值。数模比赛......
  • 【人工智能学习之聚类分析算法DBSCAN】
    【人工智能学习之聚类分析算法DBSCAN】什么是DBSCAN详细介绍对比DBSCAN和K-Means聚类算法的优缺点DBSCAN的实际应用DBSCAN调用方法具体代码示例:人群密度测算修改参数什么是DBSCANDBSCAN(Density-BasedSpatialClusteringofApplicationswithNoise),即基于密度的......
  • 【C++】IO流
    ......