字符串---第一部分 序列、字串;上升,公共

这篇具有很好参考价值的文章主要介绍了字符串---第一部分 序列、字串;上升,公共。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

第一部分 最长上升子序列,最长上升子串,最长公共子序列,最长公共子串--dp

第二部分 KMP,trie,双指针

第三部分 待定

动态规划:审题,状态确定,状态转移,边界条件

线性DP

最长上升子序列

403 线性DP 最长上升子序列【动态规划】_哔哩哔哩_bilibili

给定一个无序整数数组,找出其中最长上升子序列(LIS)的长度。

输入:【5,7,1,9,4,6,2,8,3】

输出:4

解释:最长上升子序列是【1,4,6,8】,其长度是4

如何思考解决这个问题,用s表示这个数组,设f(i)表示以s[i]结尾的的最长上升子序列长度,边界条件f(0)=1,思考当i>=1时,f(i)与f(i-1)的关系,考虑s[i]和s[i-1],或者考虑s[i]与s[0]...s[i-1],至少有一点,f(i)大于等于f(i-1),遍历s[0]...s[i-1],如果记录最大的j,使得s[j]<s[i],且j尽可能大,f(i)=max(f(i-1),f(j)+1),该递推式有问题,修正,f(i)=max(f(i),f(j)+1),这样就没有问题了,

比如5,7,1,9,4,6,2,8,3 

f(0)=1,f(1)=2,f(2)=1,f(3)=f(2)+1=3,f(4)=2,f(5)=3,f(6)=2,f(7)=4,f(8)=3 

上述的过程是可行的,记录最大的f(i)即可,就是答案,如果f(i)表示以s[i]结尾的子串的最长上升子序列,那么显然有f(i)大于f(i-1),但是难以列出状态转移方程。

另外,设f(i)表示以s[i]开头的最长上升子序列长度,从后往前遍历,对于5,7,1,9,4,6,2,8,3 这列数,一共9个数,数组下标从0开始,初始条件f(8)=1,当s[i]<s[i+1]时,更新f(i)=max(f(i),f(i+1)+1),

最长上升序列求解,重点在于如何将状态函数与字符串之间的关系唯一确定下来,如果采用以s[i]结尾的最长公共子序列长度作为f(i)的含义,从前往后搜索,可以得到转换公式;如果采用以s[i]开头的最长公共子序列长度作为f(i)的含义,改变搜索方向,同样可以得到转换的公式。如果采用s[0]...s[i]的最大上升子序列长度作为f(i)的含义,很难得到转换公式,f(i)的值(但是这个是根据题目含义最容易想的状态含义,难以求解出状态转移方程)

如何确定状态函数的含义

字符串---第一部分 序列、字串;上升,公共

 定义f(i)表示爬到高度为i时需要的期望时间,由高度i-1可以转换为两个状态,分别是高度0,概率是pi;转换为高度i,概率是1-pi;在上述定义下,难以写出转换方程

定义f(i)为从高度为i爬到树顶需要的期望时间,则f(树高度)=0,状态转移是,f(i-1)=(1-pi)*f(i)+pi*f(0)+1,需要求解的就是从树的底部(高度为0)爬到树顶经过的时间的期望值f(0).

最长公共子序列

给定两个字符串,输出其最长公共子序列的长度,输入,ADABEC与DBDCA

输出:3

解释:最长公共子序列是DBC,长度是3

从左向右扫描两个字符串a,b,指针分别使用i和j,状态变量,看作自变量i和j的函数,数据结构实现可以使用二维数组,f(i,j)表示a[0]...a[i]与b[0]...b[j]的最长公共子序列长度,f(0,0)=0,状态转移方程,如果a[i]=b[j],有f(i,j)=f(i-1,j-1)+1,如果a[i]!=b[j],分为三种情况,分别是a[i]不在最长公共子序列中,f(i,j)=f(i-1,j),b[j]不在最长公共子序列中,f(i,j)=f(i,j-1),a[i]和b[j]都不在最长公共子序列中,f(i,j)=f(i-1,j-1),其中第三种可以看成前两种的特例,如果a[i]!=b[j]有f(i,j)=max(f(i-1,j),f(i,j-1));  

最长上升子串

参考最长上升子序列做法,设f(i)表示以s[i]结尾的最长上升子串的长度,f(0)=0,如果s[i]>s[i-1],f(i)=f(i-1)+1,否则f(i)=0;最长上升子串长度是最大的f(j),j=0,1,...,n-1.

最长公共子串

参考最长公共子序列做法,设f(i,j)表示a[0]...a[i]和b[0]...b[j]的最长公共子串的长度,f(0,0)=0,如果a[i]!=b[j],f(i,j)=0;如果a[i]==b[j],则f(i,j)=f(i-1,j-1)+1;

只有当两个字符串中的字符连续相等时,公共字串的长度才不断增加。


 

最长上升公共子串

参考最长公共子序列做法,设f(i,j)表示a[0]...a[i]和b[0]...b[j]的最长公共子串的长度,f(0,0)=0,如果a[i]!=b[j],f(i,j)=0;如果a[i]>a[i-1]且b[j]>b[j-1]且a[i]==b[j]且a[i-1]==b[j-1],则f(i,j)=f(i-1,j-1)+1;如果a[i]==b[j]且a[i-1]==b[j-1]且a[i]>a[i-1],则f(i,j)=f(i-1,j-1)+1;否则,如果a[i]==b[j],则f(i,j)=1;,否则f(i,j)=0.

最长上升公共子序列

上面已经了解到最长上升子序列和最长公共子序列的求解,状态定义和状态转移方程,此处可以将二者结合

最长上升子序列的状态f(i)定义为以s[i]结尾的最长上升子串长度,当s[i]>s[i-1]时,f(i)=f(i-1)+1;当s[i]<=s[i-1]时,遍历s[0]...s[i-1],如果s[j]<s[i-1],则f(i)=max(f(i),f(j)+1),f(0)=0,结果是最大的

最长公共子串的状态定义为f(i,j)表示a[0]...a[i]和b[0]...b[j]的最长公共子串长度,初始f(0,0)=0,如果a[i]==b[j],f(i,j)=f(i-1,j-1)+1;否则,f(i,j)=0;

从上面两个可以看出,最长上升子序列长度求解复杂一些,

对于最长上升公共子序列长度求解,定义f(i,j)表示以a[i]和b[j]结尾的最长公共上升子序列长度,f(0,0)=0,如果a[i]!=b[j],f(i,j)=0;;如果a[i]==b[j],寻找最长上升公共子序列长度,待续******

对于最长上升公共子序列长度求解,定义f(i,j)表示以a[i]和b[j]结尾的最长公共上升子序列长度,f(0,0)=0,如果a[i]!=b[j],f(i,j)=0;;

如果a[i]==b[j],寻找最长上升公共子序列长度,参考最长上升子序列的求解,遍历ii=0,...i-1,jj=0,...,j-1,如果a[ii]<a[i]且b[jj]<b[j]且a[ii]==b[jj],则f(i,j)=max(f(i,j),f(ii,jj)+1);;

简化一下,遍历ii=0,...i-1,jj=0,...,j-1,如果a[ii]==b[jj]且a[ii]<a[i],则f(i,j)=max(f(i,j),f(ii,jj)+1);;

最后,输出最大的f(i,j)就是所求答案。时间复杂度是O(n^4)

#include<bits/stdc++.h>
using namespace std;
const int N=100;
//LICS
//lis,lcs
char a[N],b[N];
int f[N][N];
int max_len=-1;

void work(){
	if(a[0]==b[0])f[0][0]=1;else f[0][0]=0;
	for(int i =0 ;a[i];i++)
		for(int j = 0;b[j];j++)
			if(a[i]!=b[j]){
				f[i][j]=0;
			}else {
				f[i][j]=1;
				for(int ii=0;ii<i;ii++)
					for(int jj=0;jj<j;jj++)
						if(a[ii]==b[jj]&&a[ii]<a[i])
							f[i][j]=max(f[i][j],f[ii][jj]+1);
				max_len=max(max_len,f[i][j]);
			}
	for(int i =0 ;a[i];i++)
		for(int j = 0;b[j];j++)
			cout<<i<<" "<<j<<f[i][j]<<"\t";		
	cout<<max_len<<endl;
}
int main(){
	int n;
	cin>>n;
	for(int i = 0;i < n;i++)cin>>a[i];
	for(int i = 0;i < n;i++)cin>>b[i];
	
	work();
	return 0;
}
 

7
7 1 5 6 4 2 7
7 1 5 4 6 7 2

字符串---第一部分 序列、字串;上升,公共

 上述复杂度高的原因:对于最长上升公共子序列长度求解,定义f(i,j)表示以a[i]和b[j]结尾的最长公共上升子序列长度,f(0,0)=0,如果a[i]!=b[j],f(i,j)=0;;对于结尾元素的限制有两个,一个是字符串a,另一个是字符串b,限制了最后的1结尾的元素。

定义f(i,j)表示以a[i]和b[j]结尾的最长公共上升子序列长度,事实上,任意一个字符串只能有一个结尾,任选限制条件为a[i]或者b[j]结尾即可。

如果只限制一个结尾元素,定义f(i,j)表示以a[0]...a[i]和b[0]...b[j]的最长公共上升子序列长度,限制该最长公共子序列是以a[i]结尾的(不限制不一定要以b[i[结尾)。这样,如果a[i]!=b[jj],jj=0,...,j,那么f[i][j]=0;否则,f[i][j]至少取值为1

遍历jj=0,...,j,当a[i]==b[jj]且   ***************

AcWing 272. 最长公共上升子序列 - AcWing

     O(n^3)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;
const int N=3010;
int n;
int a[N],b[N];
int f[N][N];
int main(){
	scanf("%d",&n);
	for(int i = 1;i<=n;i++)scanf("%d",&a[i]);
	for(int i = 1;i <=n;i++)scanf("%d",&b[i]);
	for(int i = 1;i <=n;i++)
		for(int j = 1; j<= n;j++)
		{
			f[i][j]=f[i-1][j];
			if(a[i]==b[j]){
				int maxv=1;
				for(int k = 1;k< j;k++)
					if(b[k]<b[j])maxv=max(maxv,f[i-1][k]+1);
				f[i][j]=max(maxv,f[i][j]);
			}
		} 
		int res=0;
		for(int i  = 1;i <= n;i++)res=max(res,f[n][i]);
		printf("%d\n",res);
		return 0;
}

     O(n^2)文章来源地址https://www.toymoban.com/news/detail-470861.html

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;
const int N=3010;
int n;
int a[N],b[N];
int f[N][N];
int main(){
	scanf("%d",&n);
	for(int i = 1;i<=n;i++)scanf("%d",&a[i]);
	for(int i = 1;i <=n;i++)scanf("%d",&b[i]);
	for(int i = 1;i <=n;i++){
		int maxv=1;
		for(int j = 1; j<= n;j++)
		{
			f[i][j]=f[i-1][j];
			if(a[i]==b[j])
				f[i][j]=max(maxv,f[i][j]);//使用记录的最大值 
			if(b[j]<a[i])maxv=max(maxv,f[i-1][j]+1) ;
		} 
	}
	int res=0;
	for(int i  = 1;i <= n;i++)res=max(res,f[n][i]);
	printf("%d\n",res);
	return 0;
}

到了这里,关于字符串---第一部分 序列、字串;上升,公共的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 第一部分:核心容器

    Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架!         什么是IoC、IoC容器、bean、DI ? IoC:对象创建控制权由程序转移到IoC容器的控制反转思想。 IoC容器:创建管理对象的容器。 bean:IoC容器中被创建管理的对象。 DI:IoC容器中建立bean之间依赖关

    2024年02月13日
    浏览(46)
  • MySQL学习-第一部分

    MySQL数据库 MySQL是一个**关系型数据库管理系统****,**由瑞典[MySQL AB](https://baike.baidu.com/item/MySQL AB/2620844) 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用

    2024年02月15日
    浏览(52)
  • 6.播放音频(第一部分)

    这一章将对播放音频的具体内容做讲解。我的想法是按照tinyalsa中的例子作为讲解的范本,因为tinyalsa足够简单,很多时候都忽略了它的细节。趁着这个机会再整理一下tinyalsa的内容。我使用的tinyalsa从https://github.com/tinyalsa/tinyalsa下载,从examples/writei.c开始。 其中函数read_file从

    2023年04月08日
    浏览(39)
  • 第一部分:Spark基础篇

    第一部分:Spark基础篇_奔跑者-辉的博客-CSDN博客 第二部分:Spark进阶篇_奔跑者-辉的博客-CSDN博客 第三部分:Spark调优篇_奔跑者-辉的博客-CSDN博客 第一部分:Flink基础篇_奔跑者-辉的博客-CSDN博客 (*建议收藏*) 实时数仓之 Kappa 架构与 Lambda 架构_奔跑者-辉的博客-CSDN博客(*建议收

    2024年02月05日
    浏览(48)
  • 第一部分-基础篇-第一章:PSTN与VOIP(下篇)

      学习资料来源《FreeSWITCH权威指南》-作者杜金房这本书。我是2022年6月毕业的,偶然的机会接触到FreeSWITCH,但是目前在南京从事java后端开发,FreeSWITCH纯属个人爱好,进行笔记整理。也一直希望有机会可以参与FreeSWITCH相关工作开发,如有需要,请联系我18956043585,先说声谢

    2024年02月06日
    浏览(57)
  • HTML学习 第一部分(前端学习)

    参考学习网站: 网页简介 (w3schools.com) 我的学习思路是:网站+实践+视频。 视频很重要的,因为它会给你一种开阔思路的方式。你会想,噢!原来还可以这样。这是书本或者网站教程 所不能教给你的。而且,对一些教程,它的用法你可能 在工作或者以后都用不上,这种情况下

    2024年02月15日
    浏览(51)
  • Mysql入门基础教程(第一部分)

    MySQL基础教程解释了一些基本的SQL语句。如果这是您第一次使用关系数据库管理系统,本教程将为您提供使用MySQL数据库服务器所需的一切,例如查询数据,更新数据,管理数据库和创建表。 如果您已经熟悉其他关系数据库管理系统(如PostgreSQL,Oracle或Microsoft SQL Server等),

    2024年04月14日
    浏览(40)
  • 学成在线项目开发技巧整理---第一部分

    视频项目链接: 学成在线 整理的是我个人认为偏生疏的知识点,不一定涉及的全面。 在系统中某些选项是几个特定的值的一个或多个,并且随着还可以动态添加。比如支付方式,配送方式等。 此时我们应该设计一个数据字典模块,在后台进行管理,然后前台要从后端查询。并

    2023年04月22日
    浏览(59)
  • 阿里服务器怎么用教程[第一部分]

    第一步,登录我们的阿里云账号。   第二步,根据自己的具体情况,选择好服务器的配置,比如你是大型企业,预估网站访问量很大,那么就要选配置较好的服务器,如果是个人网站,预估流量较小,就可以选择配置较低的云服务器。   第三步,购买好云服务器后,我们在

    2024年02月10日
    浏览(49)
  • 【OpenCV入门】第一部分——图像处理基础

    图像处理包括4个基本操作: 读取图像 、 显示图像 、 保存图像 和 获取图像属性 。 imread() filename :目标图像的完整路径名。 flags :图像的颜色类型的标记,有0和1两个值,其中1为默认值。当读取一幅彩色图像时,如果想要得到一幅 彩色图像 ,那么flags的值为1(此时flags的

    2024年02月11日
    浏览(47)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包