注: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. org.apache.httpcomponents.httpclient

    apache org doc :http://hc.apache.org/httpcomponents-client-ga/tutorial/html/fundamentals.html#d5e49 ...

  2. Codeforces Round #567 (Div. 2) A.Chunga-Changa

    原文链接:传送 #include"algorithm" #include"iostream" #include"cmath" using n ...

  3. Gym安装ubuntu16.04

    Step1:将gym克隆到计算机上: git clone https://github.com/openai/gym.git 如果你的电脑没有安装git,那么键入 sudo apt install g ...

  4. varchar(n)

    MySQL5.0.3之前varchar(n)这里的n表示字节数MySQL5.0.3之后varchar(n)这里的n表示字符数,比如varchar(200),不管是英文还是中文都可以存放200个根据字符 ...

  5. zookeeper集群搭建记录

    本文仅记录zookeeper集群搭建的过程,留待日后查看.使用. 一.硬件机器: 192.168.183.195 master-node 192.168.183.194 data-node1 192. ...

  6. awk函数实现将点分式形式的掩码转换为十进制形式的掩码

    在用awk处理文本时,需要将源数据为点分式形式的掩码转换为十进制形式的掩码,下边的函数可简单实现: 转换功能函数cdr2mask function cdr2mask(mask_point) { num ...

  7. PHPCMS站内搜索功能实现方法汇总,一文解决PHPCMS站内搜索问题

    1,https://blog.csdn.net/hzw19920329/article/details/80110673 点评:phpcms搜索功能实现方法,作者基于PHPCMS做个门户网站实现站内搜 ...

  8. Travel in desert

    传送门 不算难吧 应该有思路的 还是太水了吧 (而且和货车运输很像的啊 ---------------------------------------------------------------- ...

  9. opencv python:直线检测 与 圆检测

    霍夫直线变换介绍 霍夫圆检测 现实中: example import cv2 as cv import numpy as np # 关于霍夫变换的相关知识可以看看这个博客:https://blog.c ...

  10. SQL中AVG、COUNT、SUM、MAX等聚合函数对NULL值的处理

    一.AVG() 求平均值注意AVE()忽略NULL值,而不是将其作为“0”参与计算 二.COUNT() 两种用法 1.COUNT(*) 对表中行数进行计数不管是否有NULL 2.COUNT(字段名) ...