LIS(最长的序列)和LCS(最长公共子)总结

LIS(最长递增子序列)和LCS(最长公共子序列)的总结

最长公共子序列(LCS):O(n^2)

两个for循环让两个字符串按位的匹配:i in range(1, len1) j in range(1, len2)

s1[i - 1] == s2[j - 1], dp[i][j] = dp[i - 1][j -1] + 1;

s1[i - 1] != s2[j - 1], dp[i][j] = max (dp[i - 1][j], dp[i][j - 1]);

初始化:dp[i][0] = dp[0][j] = 0;

伪代码:
    dp[maxn1][maxn2];
    s1[maxn1],s2[maxn2];
    p[maxn1][maxn2][2];
    //init
    for i in range(0, len1):
        dp[i][0] = 0;
    else:;
    for i in range(0, len2):
        dp[0][i] = 0;
    else:;

    for i in range(1, len1):
        for j in range(1, len2):
            if s1[i] == s2[j]:
                dp[i][j] = dp[i - 1][j - 1] + 1;
                p[i][j][0] = i - 1;
                p[i][j][1] = j - 1;
            else:
                if dp[i - 1][j] > dp[i][j - 1]:
                    dp[i][j] = dp[i - 1][j];
                    p[i][j][0] = i - 1;
                    p[i][j][1] = j;
                else:
                    dp[i][j] = dp[i][j - 1];
                    p[i][j][0] = i;
                    p[i][j][1] = j - 1;
        else:;
    else:;
    return dp[len1][len2];
    //path 非递归
    function print_path(len1, len2):
        if (dp[len1][len2] == 0)
            return;
        printf_path(p[len1][len2][0], p[len1][len2][1]);
        if s1[len1] == s2[len2]:
            printf:s1[len1];
    end function;

题目:UVA - 531Compromise
UVA - 10066The Twin Towers UVA - 10192Vacation

uva10405 - Longest Common Subsequence

最长递增子序列(LIS):O(n^2)

从左到右的求前i长度的序列的最长递增子序列的长度,状态转移方程:

dp[i] = Max(dp[j] + 1);i in range(1, len); j in range(1, i - 1);

伪代码
    s[maxn],dp[maxn];

    for i in range(1, len):
        dp[i] = 1;

    int maxlen = 1;
    for i in range(2, len):
        for j range(1, i - 1):
            if s[i] > s[j]:
                dp[i] = Max(dp[i], dp[j] + 1);
        else:
            maxlen = max(maxlen, dp[i]);
    else:;
    return maxlen;
    //path递归
    function print_path(maxlen):
        if maxlen == 0:return;

        for i in range(1, len):
            if dp[i] == maxlen:
                print_path(maxlen - 1);
                printf:s[i];
    end function;

题目:UVA - 10599Robots(II)

最长递增子序列O(n * logn)

还是从左往右的求前i长度的序列的最长递增子序列长度,可是再确定dp[j]最大值的时候还要用一层循环来查找。这样比較低效.假设把前面的i长度序列出现的最长递增子序列储存起来,那么查找的时候用二分就能够做到O(logn)的复杂度。

用一个LIS数组来储蓄前i序列的最长递增子序列,查找第i个数字的时候,假设num[i] > LIS[top], 那么LIS[++top] = num[i]; dp[i] = top;假设num[i] == LIS[top],那么dp[i] = top; 假设num[i] < LIS[top], 那么二分查找到某个等于或者大于num[i]的最接近的值的位置(第k个),dp[i] = k - 1; LIS[k] = num[i];

题目:UVA - 10534Wavio Sequence

伪代码
    dp[maxn], LIS[maxn], s[maxn];
    top = 0;
    LIS[top++] = s[1];

    int maxlen = 1;
    for i in range(2, len):
        if s[i] > LIS[top]:
            LIS[++top] = s[i];
            dp[i] = top + 1;
        else if s[i] == LIS[top]:
            dp[i] = top + 1;
        else:
            k = lower_bound(LIS.begin(), LIS.end(), s[i]) - LIS.beign();
            LIS[k] = s[i];
            dp[i] = k + 1;

        maxlen = max(maxlen, dp[i]);
    else:;
    return maxlen;
最长公共子序列O(n * logn)

要求串本身不会出现同样的数字或是字母。通过对第一个字符串进行映射(递增的顺序)。然后第二个字符串按照上面的第一个字符串等价映射,这样就把问题从LCS转化成LIS。比如:

串1: 2 4 3 5 6

映射:1 2 3 4 5

串2: 3 2 6 8 10

等价映射:3 1 5 0 0

题目:uva10635Prince and Princess

版权声明:本文博客原创文章,博客,未经同意,不得转载。

时间: 2024-11-05 14:41:31

LIS(最长的序列)和LCS(最长公共子)总结的相关文章

算法设计 - LCS 最长公共子序列&amp;&amp;最长公共子串 &amp;&amp;LIS 最长递增子序列

出处 http://segmentfault.com/blog/exploring/ 本章讲解:1. LCS(最长公共子序列)O(n^2)的时间复杂度,O(n^2)的空间复杂度:2. 与之类似但不同的最长公共子串方法.最长公共子串用动态规划可实现O(n^2)的时间复杂度,O(n^2)的空间复杂度:还可以进一步优化,用后缀数组的方法优化成线性时间O(nlogn):空间也可以用其他方法优化成线性.3.LIS(最长递增序列)DP方法可实现O(n^2)的时间复杂度,进一步优化最佳可达到O(nlogn)

LIS(最长递增子序列)和LCS(最长公共子序列)的总结

最长公共子序列(LCS):O(n^2) 两个for循环让两个字符串按位的匹配:i in range(1, len1) j in range(1, len2) s1[i - 1] == s2[j - 1], dp[i][j] = dp[i - 1][j -1] + 1; s1[i - 1] != s2[j - 1], dp[i][j] = max (dp[i - 1][j], dp[i][j - 1]); 初始化:dp[i][0] = dp[0][j] = 0; 伪代码: dp[maxn1][ma

最长增长序列的长度(LIS)

我最早的思路是反过来遍历,结果总是不对.因为老是觉得动态规划就是列递归,所以一心琢磨着怎样递归,导致一直不对. 正确的思路应该是什么呢?应该是尝试用符号表示其最优的状态和其子状态,然后找出状态之间转移的方法.最后实现这个方法. 最长增长序列的最优状态是什么样子呢?既然是最长,肯定是要容纳尽可能多的元素,怎样容纳尽可能多的元素呢?那就是较小值尽可能小. 那么遍历到的新元素就存在两种情况: 1. 新元素比已知当前 LIS  中的每个元素都要大,那毫无疑问应该加入 LIS. 2. 新元素比当前 LIS

zoj1986 Bridging Signals (dp,最长递增序列,LIS)

A - Bridging Signals Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%lld & %llu Submit Status Practice ZOJ 1986 Description 'Oh no, they've done it again', cries the chief designer at the Waferland chip factory. Once more the routing designer

LIS 最长上升序列

#include <iostream> #include <stdlib.h> using namespace std; #define MAX 10000 int num[MAX], n; /*********************************************************************************************** 经典的O(n^2)的动态规划算法,设num[i]表示序列中的第i个数, dp[i]表示从1到i这一段

数据结构与算法学习之路:LIS——最长递增序列的动态规划算法和二分思想算法

一.最长递增序列的问题描述: 求一个整数序列的最长递增子序列,子序列不要求是连续的.例如: Input:4,6,9,6,7,6,3,8,10:Output:5 二.解决方法: 1.用动态规划的方法解决.从问题我们可以知道,我们最终得到的最长递增子序列,其任意一段子序列也是对应序列中的最长子序列.这样说可能不好理解,就以上面的例子来说: 最长子序列为:4,6, 7, 8, 10.在这段子序列的子序列里选一个,例如:4,6,7.则4,6,7也是4,6,9,6,7,6,3这段序列的最长子序列. 对于动

求解两个序列的所有最长公共子序列(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>, 

lcs(最长公共子序列),dp

lcs(最长公共子序列) 求两个序列的lcs的长度,子序列可不连续 dp[i][j]=dp[i-1][j-1]+1(a[i]==b[i]) dp[i][j]=max(dp[i-1][j],dp[i][j-1])(a[i]!=b[i]) memset(dp,0,sizeof(dp)); for(int i=1;i<=n1;i++){ for(int j=1;j<=n2;j++){ if(a[i]==b[j]) dp[i][j]=dp[i-1][j-1]+1; else dp[i][j]=max(

lightoj 1110 - An Easy LCS 最长公共子序列+string

1110 - An Easy LCS PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB LCS means 'Longest Common Subsequence' that means two non-empty strings are given; you have to find the Longest Common Subsequence between them. Since there