C++ 求解最长公共子序列(不仅仅求出其大小)(简单易懂!!!)(动态规划)

这篇具有很好参考价值的文章主要介绍了C++ 求解最长公共子序列(不仅仅求出其大小)(简单易懂!!!)(动态规划)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

求解两个数组的最长公共子序列我们需要用到的知识点有:动态规划dp,递归算法

先来说说动态规划dp 很多初学者在学习动态规划的时候总是百思不得其解,什么是动态规划呢,其实总结来说就是程序将计算过的结果记录下来,在下次使用到这条记录的时候不需要再次计算,而可以直接使用,这样看来是不是节省了很大的时间开销呢!

动态规划解决问题一般套路可以分为两步,1:自顶向下的分析问题 2:自底向上的解决问题

为什么要自顶向下的分析问题呢? 我们要知道问题在多数值的情况下往往会具有一般性。

而自底向上的解决问题则是因为数据是从最底的数据开始记录,由少的数值计算得出多的数值。

我们可以用盖房子为例子,工程师是负责设计架构的,一般是从房子的头部开始向下设计,而建造房子则是需要从最底部开始搭建,所以自顶向下的设计,自底向上的解决。

现在回到我们的问题上,求两个字符串的最长序列,假设第一个字符串为S1,字符长度为i,第二个字符串为S2,字符长度为j。建立二维数组dp[i+1][j+1],dp[i][j]的意思为第一个字符串的前i个与第二个字符串的前j个的最长子序列。我们自顶向下的分析问题即从S1的最后一个即第i个与S2的最后一个即第j个进行判断。显而易见可以看出假如S1[i]==S2[j]相等的话那么i与j判断完毕,接下来就从i-1与j-1开始判断(因为i与j判断完毕就往前判断)故dp[i][j]=dp[i-1][j-1]+1。

假如S1[i]==S2[j]不相等的话,那么会出现两种情况,要知道最大子序列是两者共有的,那么i和j不相等,他们之中一定有一个不在子序列当中,所以要么i不在,要么j不在,i不在那么我们就从i-1开始找,j不在我们就从j-1开始找。故dp[i][j]=max(dp[i-1][j],dp[i][j-1])。

代码如下:

	for(int p=1;p<=i;p++)// i为S1的长度       p,q皆从1开始往后面循环                          
	{
		for(int q=1;q<=j;q++) //j为S2的长度      自底向上解决问题
		{
			
			if(s1[p-1]==s2[q-1])  //字符串从0开始 这里容易出错
			{
				dp[p][q]=dp[p-1][q-1]+1;
			}
			else
			{
				dp[p][q]=max(dp[p-1][q],dp[p][q-1]);
			}
			
		}
	}

这样我们就可以得到最长子序列的长度了,可以这样我们无法得知最长子序列到底是什么样的?

想要得出这个结果,我们就需要使用递归来解决。

在先前我们已经得出了dp数组的完整数值,我们可以使用dp数组的值递归来解决,我们先准备一个空数组,假如S1[i]==S[j],那么我们就可以直接把这个值记录到数组里,假如他们不相等,那么就是上面的情况了分别是i不在和j不在。具体我们已经通过dp计算出来了即dp[i][j]==dp[i-1][j]那么就是i不在序列中,我们从S1的第1个到i-1个与S2的第1个到第j个开始寻找。dp[i][j]==dp[i][j-1]那么就是j不在序列中,我们从S1的第1个到i个与S2的第1个到第j-1个开始寻找。这样重复递归,当i等于0或者j为0时停止递归。

代码如下:

void found(string a,string b,int i,int j,char rem[],int dp[][100]){
 	if(i==0 ||j==0){
 		
	 return;
 	
	 }
 	if(a[i-1]==b[j-1])
 	{
 		rem[m]=a[i-1];
 		m++;
 		found(a,b,i-1,j-1,rem,dp);
	 }
	 else{
	 	if(dp[i][j]==dp[i-1][j])
	 	found(a,b,i-1,j,rem,dp);
	 	else if (dp[i][j]==dp[i][j-1])
	 	found(a,b,i,j-1,rem,dp);
	 	
	 }
		
	}

所以总体的代码为:

#include<iostream>
using namespace std;
#include<algorithm>
#include <cstring>
int m;   //m用来记录两个字符串相等的个数
void found(string a,string b,int i,int j,char rem[],int dp[100][100]);

int main()
{
	string s1;
	string s2;
	int i,j;
	cout<<"请输入第一个字符串:"; 
	cin>>s1;
	cout<<"请输入第二个字符串:"; 
	cin>>s2;
	i=s1.length();
	j=s2.length();
	int dp[i+1][100];
	char rem[max(i,j)];
	memset(dp,0,sizeof(dp));
	for(int p=1;p<=i;p++)
	{
		for(int q=1;q<=j;q++)
		{
			
			if(s1[p-1]==s2[q-1])
			{
				dp[p][q]=dp[p-1][q-1]+1;
			}
			else
			{
				dp[p][q]=max(dp[p-1][q],dp[p][q-1]);
			}
			
		}
	}
    
	cout<<"最大子序列的个数为:"<<dp[i][j]<<endl;
	
	found(s1,s2,i,j,rem,dp);
	for(int g=m-1;g>=0;g--)     //因为是逆序保存的所以需要逆序输出
	{
		cout<<rem[g];
	}

	
}
void found(string a,string b,int i,int j,char rem[],int dp[][100]){
 	if(i==0 ||j==0){
 		
	 return;
 	
	 }
 	if(a[i-1]==b[j-1])
 	{
 		rem[m]=a[i-1];
 		m++;
 		found(a,b,i-1,j-1,rem,dp);
	 }
	 else{
	 	if(dp[i][j]==dp[i-1][j])
	 	found(a,b,i-1,j,rem,dp);
	 	else if (dp[i][j]==dp[i][j-1])
	 	found(a,b,i,j-1,rem,dp);
	 	
	 }
		
	}

运行结果案例如下:

动态规划最长公共子序列问题c++,c++,算法,开发语言

 文章来源地址https://www.toymoban.com/news/detail-765746.html

 

 

到了这里,关于C++ 求解最长公共子序列(不仅仅求出其大小)(简单易懂!!!)(动态规划)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【可观察性架构】什么是可观察性? 不仅仅是日志、指标和跟踪

    随着动态系统架构的复杂性和规模的增加,IT 团队面临着越来越大的压力来跟踪和响应其多云环境中的条件和问题。因此,IT 运营、DevOps 和 SRE 团队都在寻找对这些日益多样化和复杂的计算环境的更高可观察性。 但什么是可观察性?为什么它很重要,它实际上可以帮助组织实

    2024年02月10日
    浏览(42)
  • Mac Snipaste 不仅仅是截图工具,不在菜单栏显示,怎么样修改快捷键

    官网下载: https://www.snipaste.com Snipaste 免费,支持 Windows、Mac,Windows 上的功能相当多而且,Mac 也够用了 不仅仅是个截图工具,具有强大功能: 截图 贴图(直接将截图贴在桌面上,当标签贴使用) 取色器 fn + F1: 开始截屏 C : 取色 Tab : 检测窗口 + 滑动触控板,选择要截屏的

    2024年02月08日
    浏览(30)
  • 从星巴克看:NFT不仅仅是一种数字资产,更代表着一种全新的交互模式

    品牌方不应将数字化的生意局限在NFT收藏品上,更需另辟蹊径,比如说粉丝通证。“粉丝通证与其说是一个概念,更准确的描述一种运营系统,而任何以此为基础进行的活动都是只是一种实现方式。如果发行的品牌方有强大影响力或者‘信心’,那么发售一款NFT收藏品是最简

    2024年02月11日
    浏览(42)
  • 算法套路十五——动态规划求解最长公共子序列LCS

    给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。 一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。

    2024年02月04日
    浏览(42)
  • C++ 动态规划经典案例解析之最长公共子序列(LCS)_窥探递归和动态规划的一致性

    动态规划处理字符相关案例中,求 最长公共子序列 以及求 最短编辑距离 ,算是经典中的经典案例。 讲解此类问题的算法在网上一抓应用一大把,即便如此,还是忍不住有写此文的想法。毕竟理解、看懂都不算是真正掌握,唯有瞧出其中玄机,能有自己独有的见解和不一样

    2024年02月13日
    浏览(28)
  • 最长公共子序列和最长公共子串

    最长公共子序列 题目描述 给出1,2,…, n 的两个排列P 1 和 P 2 ,求它们的最长公共子序列。 输入格式 第一行是一个数 n 。 接下来两行,每行为 n 个数,为自然数1,2,…, n 的一个排列。 输出格式 一个数,即最长公共子序列的长度。 题目分析 第一阶段定义dp数组 (1)考虑规模

    2024年02月19日
    浏览(25)
  • 【算法训练-字符串 三】最长公共子串、最长公共子序列

    废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是【】,使用【】这个基本的数据结构来实现,这个高频题的站点是: CodeTop ,筛选条件为: 目标公司+最近一年+出现频率排序 ,由高到低的去 牛客TOP101 去找,只有两个地方都出现过才做

    2024年02月09日
    浏览(31)
  • 代碼隨想錄算法訓練營|第五十五天|1143.最长公共子序列、1035.不相交的线、53. 最大子序和。刷题心得(c++)

    目录 讀題 1143.最长公共子序列 自己看到题目的第一想法 看完代码随想录之后的想法 1035.不相交的线 自己看到题目的第一想法 53. 最大子序和 看完代码随想录之后的想法 1143.最长公共子序列 - 實作 思路 Code 1035.不相交的线 - 實作 思路 Code 53. 最大子序和 - 實作 思路 Code 總結

    2024年02月06日
    浏览(51)
  • 【LeetCode动态规划#14】子序列系列题(最长递增子序列、最长连续递增序列、最长重复子数组、最长公共子序列)

    力扣题目链接(opens new window) 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。 子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。 示例 1: 输入:nums = [10,9,2,5,3,7,101,18] 输出

    2024年02月01日
    浏览(46)
  • 动态规划——最长公共子序列

    先来讲解以下什么是最长公共子序列。最长公共子序列不是最长相同字符串,有点相似但不一样,来举个简单的例子,有字符串s1=bcdea,s2=abce,最长相同字符串是bc,最大公共部分是2;而最长公共子序列则是bce,最大公共部分是3。可以看出,公共子序列不需要连续相等,有相

    2023年04月19日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包