dp求解各种子串子序列
注:dp可能并不是求解该这些问题的最优算法,这里只是做一个dp 算法的简介。
概念
定义:假设现有一个 string = abcdefghijklmn
最长连续子串:要求在原序列中连续,比如 str = abcd、fghijklm都是valid substring
最长连续子序列:相对顺序在原序列中不变即可;比如 str = afgh、dfkn等等都是valid subsequence
说完了上面的定义;下面来说一说怎么用dp求解最长连续子串和最长连续子序列;既然用到了dp 的方法求解,就要找出相关的状态转移方程。
最长上升子序列
#include <bits/stdc++.h>
using namespace std;
const int maxn=3e4+10;
int a[maxn],b[maxn],n;
int dp[maxn],ans; //dp[i]表示前i个的最长上升子序列
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){
dp[i]=1;
for(int j=1;j<i;++j){
if(a[j]<a[i]&&b[j]<b[i]) dp[i]=max(dp[i],dp[j]+1);
ans=max(ans,dp[i]);
}
}
printf("%d\n",ans);
system("pause");
}
最长连续子串
递推方程:
int f[maxn][maxn];
int solve(char *x, char *y)
{
int ans=0;
int lenx=strlen(x);
int leny=strlen(y);
for (int i=0;i<lenx;i++)
{
for (int j=0;j<leny;j++){
if (x[i]!=y[j]) f[i][j]=0;
else if(x[i]==y[j]) f[i][j]=f[i-1][j-1]+1;
ans=max(ans,f[i][j]);
}
}
return ans;
}
最长公共子序列
状态转移方程:
模板(花里胡哨的dp请忽略,网上版本,也可成二维数组):
int dp[maxn][maxn]; //a[1]~a[i]与b[1]~b[j]的最长公共子序列
int solve(int n,int m)
{
for (int i=0;i<=n;i++) dp[i][0] = 0;
for (int i=0;i<=m;i++) dp[0][i] = 0;
for (int i=1;i<=n;i++){ //n,m分别为两个数组的长度
for (int j=1;j<=m;j++){
if (a[i]==b[j]) dp[i][j]=dp[i-1][j-1]+1;
else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
return dp[n][m];
}
最长公共上升子序列
dp[i][j]的含义同最长公共子序列;
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int maxn=3e3+10;
int a[maxn],b[maxn];
int dp[maxn][maxn]; //表示a[1]~a[i]与b[1]~b[j]且以b[j]为结尾的最长上升公共子序列
int main()
{
int n;
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){
if(a[i]==b[j]){
dp[i][j]=1;
for(int k=1;k<j;++k){
if(b[k]<a[i]) dp[i][j]=max(dp[i][j],dp[i-1][k]+1);
}
}
else dp[i][j]=dp[i-1][j];
}
}
int ans=0;
for(int i=1;i<=n;++i) ans=max(ans,dp[n][i]);
printf("%d\n",ans);
system("pause");
}
上面是未优化前的代码;起代码复杂度未O(n^3);其中的k循环可以被优化;优化后时间复杂度为O(n^2),看代码:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int maxn=3e3+10;
int a[maxn],b[maxn];
int dp[maxn][maxn]; //表示a[1]~a[i]与b[1]~b[j]且以b[j]为结尾的最长上升公共子序列
int main()
{
int n;
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){
dp[i][j]=dp[i-1][j];
if(a[i]==b[j]) dp[i][j]=max(dp[i][j],maxv);
if(b[j]<a[i]) maxv=max(maxv,dp[i][j]+1);
}
}
int ans=0;
for(int i=1;i<=n;++i) ans=max(ans,dp[n][i]);
printf("%d\n",ans);
system("pause");
}
dp求解各种子串子序列的更多相关文章
- DP——最长上升子序列(LIS)
DP——最长上升子序列(LIS) 基本定义: 一个序列中最长的单调递增的子序列,字符子序列指的是字符串中不一定连续但先后顺序一致的n个字符,即可以去掉字符串中的部分字符,但不可改变其前后顺序. LIS ...
- HDU 1087 简单dp,求递增子序列使和最大
Super Jumping! Jumping! Jumping! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 ...
- hdu 1025 dp 最长上升子序列
//Accepted 4372 KB 140 ms //dp 最长上升子序列 nlogn #include <cstdio> #include <cstring> #inclu ...
- LeetCode OJ 322. Coin Change DP求解
题目链接:https://leetcode.com/problems/coin-change/ 322. Coin Change My Submissions Question Total Accep ...
- 动态规划(Dynamic Programming, DP)---- 最大连续子序列和
动态规划(Dynamic Programming, DP)是一种用来解决一类最优化问题的算法思想,简单来使,动态规划是将一个复杂的问题分解成若干个子问题,或者说若干个阶段,下一个阶段通过上一个阶段的结 ...
- uva 10069 Distinct Subsequences(高精度 + DP求解子串个数)
题目连接:10069 - Distinct Subsequences 题目大意:给出两个字符串x (lenth < 10000), z (lenth < 100), 求在x中有多少个z. ...
- 算法练习--- DP 求解最长上升子序列(LIS)
问题描写叙述: 对于2,5,3,1,9,4,6,8,7,找出最长上升子序列的个数 最长上升子序列定义: 对于i<j i,j∈a[0...n] 满足a[i]<a[j] 1. 找出DP公式:d ...
- 洛谷 P1020 导弹拦截(dp+最长上升子序列变形)
传送门:Problem 1020 https://www.cnblogs.com/violet-acmer/p/9852294.html 讲解此题前,先谈谈何为最长上升子序列,以及求法: 一.相关概念 ...
- HDU 4632 Palindrome subsequence(区间DP求回文子序列数)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4632 题目大意:给你若干个字符串,回答每个字符串有多少个回文子序列(可以不连续的子串).解题思路: 设 ...
随机推荐
- MySQL对大小写敏感吗
见字如面,见标题知内容.你有遇到过因为MYSQL对大小写敏感而被坑的体验吗? 之前看过阿里巴巴Java开发手册,在MySql建表规约里有看到: [强制]表名.字段名必须使用小写字母或数字 , 禁止出现 ...
- Codeforces Global Round 3:B. Born This Way
Born This Way原文链接:[传送门] 题目大意:潇洒哥想乘坐飞机从A地到达C地,但是没有直达的航班,在A地和B地之间有一个可以中转的航班B,潇洒哥想早点到达C地(有航班就坐),但是很不幸他得 ...
- python中使用graphviz环境配置
去官网下载graphviz,并下一步安装 配置graphviz的bin目录到path环境变量下 python相关包: 使用conda注意:conda install graphviz 可能没用,要使用 ...
- JQuery选择器(转载)
原文:https://blog.csdn.net/colorapp/article/details/44279645 一. jQuery选择器是什么1. CSS选择器要是某个样式应用于特定的HTML元 ...
- python获取进程id号:
python获取进程id号: os.getpid()获取当前进程id os.getppid()获取父进程id
- linux 网络数据收发网络流量监控
网卡流量 1.iftop命令 iftop可以用来监控网卡的实时流量(可以指定网段).反向解析IP.显示端口信息.TCP/IP连接等官网:http://www.ex-parrot.com/~pdw/if ...
- 唠唠C++二级指针、二维数组、指针数组、数组指针等的区分
今天看c++primer第六章,有这部分的内容,脑子有点糊涂了,看了几篇博客,自己敲了下,记录一下备忘. 二级指针: int **p; 二维数组: int p[10][10]; char q[10][ ...
- 猴博士4小时讲完C语言视频教程
猴博士4小时讲完C语言视频教程,一共有9节课. 目录结构如下: 目录:/2020030-猴博士4小时讲完C语言 [1G] ┣━━1.C语言基本语句(上)(更多资源访问:www.jimeng365.cn ...
- Linux安装Redis服务
下载:wget http://download.redis.io/releases/redis-5.0.5.tar.gz 解压:tar -zxvf redis-5.0.5.tar.gz 进入redi ...
- wordpress 上传图片出现权限或者http错误
首先上传图片的时候出现了 5.jpg 无法建立目录“wp-content/uploads”/2018/07.有没有上级目录的写权限? 然后啊,找方法啊 1.把var/www/wp-content/up ...