最长上升子序列问题/最长公共子序列问题

这个时候边界不是很好确定,所以可以使用记忆化搜索比较容易一点

需要注意的一点是:

更新状态的时候,一定要使用dp(x),而不是d[x]

#include<cstdio>
#include<algorithm>
using namespace std;

int A[] = {0,1,5,2,6,8,7};
int B[] = {0,2,3,5,6,9,8,4};

const int maxn = 10;
int d[maxn][maxn];//i,j代表A1~i与B1~j的最长公共子序列
int vis[maxn][maxn];

//如果a[i] == b[j] 那么d[i][j] = d[i - 1][j - 1] + 1;
//如果a[i] != b[j] 那么d[i][j] = max(d[i - 1][j],d[i][j - 1])
//但是需要注意边界,即i或者j上面有1的就是边界
//d[1][1] = 0 / 1

//记忆化搜索更容易理解,适用于不容易求边界的情况
int dp_LCS(int i,int j)
{
    if(vis[i][j])
        return d[i][j];
    vis[i][j] = 1;
    if(i == 0 || j == 0)
    {
        d[i][j] = 0;
        return 0;
    }
    if(A[i] == B[j])
    {
        d[i][j] = dp_LCS(i - 1,j - 1) + 1;
        return d[i][j];
    }
    if(A[i] != B[j])
    {
        d[i][j] = max(dp_LCS(i - 1,j),dp_LCS(i,j - 1));
        return d[i][j];
    }
}
//
int d_LIS[maxn];//d[i]表示从1~i的最长上升子序列,d[i] = max{d[j]|j < i && A[j] < A[i]}
int vis_LIS[maxn];

int dp_LIS(int i)
{
    if(vis_LIS[i])
        return d_LIS[i];
    vis_LIS[i] = 1;
    d_LIS[i] = 0;
    for(int j = 1;j < i;j++)
    {
        if(A[j] < A[i])
        {
            d_LIS[i] = max(d_LIS[i],dp_LIS(j));
        }
    }
    d_LIS[i] += 1;
    return d_LIS[i];
}

int main()
{
    memset(vis,0,sizeof(vis));
    memset(vis_LIS,0,sizeof(vis_LIS));
    dp_LCS(6,7);
    dp_LIS(6);
    return 0;
}

原文地址:https://www.cnblogs.com/TorettoRui/p/10483023.html

时间: 2024-10-11 21:26:02

最长上升子序列问题/最长公共子序列问题的相关文章

求解两个序列的所有最长公共子序列(LCSes)

 摘要 本篇博文提供了实现求解所有最长公共子序列的程序实现,并提供输出所有公共子序列的方法解释,需要具备基础知识是求解一个公共子序列的动态规划方法,请自行查阅相关资料. 题目重述 子序列概念:设X=< x1, x2,┅, xm>,若有1≤i1< i2< ┅ <ik≤m,使得Z=< z1, z2,┅, zk> = < xi1, xi2,┅, xik>,则称Z是X的子序列,记为Z<X. 例如: X=<A,B,C,B,D,A,B>, 

UVA10100:Longest Match(最长公共子序列)&amp;&amp;HDU1458Common Subsequence ( LCS)

题目链接:http://blog.csdn.net/u014361775/article/details/42873875 题目解析: 给定两行字符串序列,输出它们之间最大公共子单词的个数 对于给的两个序列X 和 Y,用i 和 j分别作为它们的前缀指针,f[i][j]表示序列X的前缀Xi 和 序列Y的前缀Yi 的最长公共子序列的长度,在这道题中,可把每一个单词当作一个字符来进行比较. 当 i | j 为0时 ,此 f[i][j] = 0; 当 i!=0 && j!=0 &&

公共子序列与公共子串问题

1.公共子序列问题 网上有很多关于公共子序列问题,说的大同小异,看了很多不明白,很多都是晦涩难懂,这里分享一个连接,个人觉得讲述的比较明白,易懂. http://blog.csdn.net/v_july_v/article/details/6695482 我这里也简单的把自己的理解说一下,求公共子序列问题是一个非常常见的问题,最差的方法就是暴力匹配,暴力匹配算法第一步求去短字符串的所有序列组合,然后从长到短一个一个的去匹配时候有公共序列相同,即使使用了这样的剪枝,该算法效率任然很低. 比较受人青

14-高效求最长公共子序列(二维数组存不下)

/*                                   See LCS again时间限制:1000 ms  |  内存限制:65535 KB难度:3 描述 There are A, B two sequences, the number of elements in the sequence is n.m; Each element in the sequence are different and less than 100000. Calculate the length

最长公共子序列的代码实现

关于最长公共子序列(LCS)的相关知识,http://blog.csdn.net/liufeng_king/article/details/8500084 这篇文章讲的比较好,在此暂时不再详说. 以下是我代码实现两种方式:递归+递推: 1 #include <bits/stdc++.h> 2 using namespace std; 3 int A[100]; 4 int B[100]; 5 6 //int B[]={2,3,5,6,9,8,4}; 7 int d[100][100]={0};

NYOJ 36 &amp;&amp;HDU 1159 最长公共子序列(经典)

链接:click here 题意:tip:最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCS(Longest Common Subsequence).其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列. 输入 第一行给出一个整数N(0<N<100)表示待测数据组数 接下来每组数据两行,分别为待测的两组字符串.每个字符串长度不大于1000. 输出 每组测试数据输出一个整数,表示最长公共子序列长度.每组

poj1159 Palindrome(最长公共子序列)

Palindrome Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 52966   Accepted: 18271 Description A palindrome is a symmetrical string, that is, a string read identically from left to right as well as from right to left. You are to write a

最长公共子序列(LCS)问题

最长公共子串(Longest Common Substirng)和最长公共子序列(Longest Common Subsequence,LCS)的区别为:子串是串的一个连续的部分,子序列则是从不改变序列的顺序,而从序列中去掉任意的元素而获得新的序列:也就是说,子串中字符的位置必须是连续的,子序列则可以不必连续. 1.序列str1和序列str2 ·长度分别为m和n: ·创建1个二维数组L[m.n]: ·初始化L数组内容为0 ·m和n分别从0开始,m++,n++循环: - 如果str1[m] ==

Longest Common Substring(最长公共子序列)

Longest Common Substring Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 37 Accepted Submission(s): 28   Problem Description Given two strings, you have to tell the length of the Longest Common Su

最长公共子序列针对小字符集的算法

一般对于两个字符串,长度分别为n和m,其时间复杂度为O(nm). 但是针对小字符集的情况,可以把复杂度降低到O(n^2),其中n为两个字符串较短的长度.这种方法对于两个字符串长度相差很大的情况比O(nm)要优化很多. 就假设所有的字符都是小写字母,这样就符合小字符集的前提了.设较短的字符串为S1,较长的字符串为S2.字符串下标从1开始. S2字符串每个位置右边第一个字符是可以通过O(km)预处理得到的.其中k为小字符集的字符个数,m为较长的那个字符串的长度. 用next[i][j]表示S2[i]