zoukankan      html  css  js  c++  java
  • 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


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

  • 相关阅读:
    BeanUtils.copyProperties的用法
    WinRAR下载
    安装Perl
    @Value设置默认值
    AutoHotkey
    解决springboot启动日志异常问题
    除以2换成位移操作(骚)
    IDEA生成doc文档生成chm文档
    VMWare虚拟机网络配置
    EOF小结
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/4668264.html
Copyright © 2011-2022 走看看