注:dp可能并不是求解该这些问题的最优算法,这里只是做一个dp 算法的简介。

概念

定义:假设现有一个 string = abcdefghijklmn

最长连续子串:要求在原序列中连续,比如 str = abcdfghijklm都是valid substring

最长连续子序列:相对顺序在原序列中不变即可;比如 str = afghdfkn等等都是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求解各种子串子序列的更多相关文章

  1. DP——最长上升子序列(LIS)

    DP——最长上升子序列(LIS) 基本定义: 一个序列中最长的单调递增的子序列,字符子序列指的是字符串中不一定连续但先后顺序一致的n个字符,即可以去掉字符串中的部分字符,但不可改变其前后顺序. LIS ...

  2. HDU 1087 简单dp,求递增子序列使和最大

    Super Jumping! Jumping! Jumping! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 ...

  3. hdu 1025 dp 最长上升子序列

    //Accepted 4372 KB 140 ms //dp 最长上升子序列 nlogn #include <cstdio> #include <cstring> #inclu ...

  4. LeetCode OJ 322. Coin Change DP求解

    题目链接:https://leetcode.com/problems/coin-change/ 322. Coin Change My Submissions Question Total Accep ...

  5. 动态规划(Dynamic Programming, DP)---- 最大连续子序列和

    动态规划(Dynamic Programming, DP)是一种用来解决一类最优化问题的算法思想,简单来使,动态规划是将一个复杂的问题分解成若干个子问题,或者说若干个阶段,下一个阶段通过上一个阶段的结 ...

  6. uva 10069 Distinct Subsequences(高精度 + DP求解子串个数)

    题目连接:10069 - Distinct Subsequences 题目大意:给出两个字符串x (lenth < 10000), z (lenth < 100), 求在x中有多少个z. ...

  7. 算法练习--- 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 ...

  8. 洛谷 P1020 导弹拦截(dp+最长上升子序列变形)

    传送门:Problem 1020 https://www.cnblogs.com/violet-acmer/p/9852294.html 讲解此题前,先谈谈何为最长上升子序列,以及求法: 一.相关概念 ...

  9. HDU 4632 Palindrome subsequence(区间DP求回文子序列数)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4632 题目大意:给你若干个字符串,回答每个字符串有多少个回文子序列(可以不连续的子串).解题思路: 设 ...

随机推荐

  1. THINKPHP 模板上传图片--后台接收图片

    模板 {extend name="public/base" /} {block name="body"} <div class="row&quo ...

  2. JS高级---复习

    复习 面向过程和面向对象都是编程的思想, 方式不一样 面向过程: 凡事都是亲力亲为, 所有的代码都要自己写, 每一步都要很清楚, 注重的是过程 面向对象: 执行者成为指挥者, 只要找对象, 然后让对象 ...

  3. servlet常用对象

    Cookie对象 浏览器缓存技术,只存储在浏览器中 cookie的大小在4kb左右,每个浏览器在同一域名下能存放cookie数量是有限的 优缺点:提高网页的效率,减轻服务器的负载;安全性较差. 1 创 ...

  4. Git的基本使用 -- 历史版本、版本回退

    查看提交的日志(历史版本) git log 不能查看已删除的commit记录 git reflog 可以查看所有分支的所有操作记录,包括已删除的commit记录 版本回退 git reset --ha ...

  5. 【StarUML】组件图

    架构设计中可视化地表达各个组件之间依赖关系以及组件的接口调用情况 1.元素 a.组件 b.接口 b1.组件暴露接口 暴露接口,需要先画一个接口 然后建立组件和接口的联系,这里是暴露接口,那么这个连线就 ...

  6. vue中用 async/await 来处理异步

    原文作者:https://www.cnblogs.com/SamWeb/p/8417940.html 昨天看了一篇vue的教程,作者用async/ await来发送异步请求,从服务端获取数据,代码很简 ...

  7. Java - JVM - jinfo

    1. 概述 jinfo java 运行时的配置工具 查看 设置 2. 环境 idea 2018.2 java jdk8 3. 准备 写个 死循环 概述 需要查看 jvm 的信息, 必须有个运行中的 j ...

  8. PHP实现敏感词过滤

    1.敏感词过滤方法 /** * @todo 敏感词过滤,返回结果 * @param array $list 定义敏感词一维数组 * @param string $string 要过滤的内容 * @re ...

  9. STL总结 (C++)

    一.一般介绍 STL(Standard Template Library),即标准模板库,是一个具有工业强度的,高效的C++程序库.它被容纳于C++标准程序库(C++ Standard Library ...

  10. eclipse中怎么导入git库下载下来的web项目

    总的看来是有两种方式: 方式一:可以对已经从版本库下载到本地的项目操作(Maven导入) 你可以通过公司提供的内部的版本库的网址登录版本库,之后在里面下载自己想要的那个版本的代码包,见下图 点击右侧的 ...