美文网首页
第22章 最长公共子序列和编辑距离

第22章 最长公共子序列和编辑距离

作者: 得力小泡泡 | 来源:发表于2020-04-03 15:54 被阅读0次

1、最长公共子序列

算法分析

image.png

时间复杂度O(n^2)

Java 代码

import java.util.Scanner;

public class Main {
    static int N = 1010;
    static int n,m;
    static int[][] f = new int[N][N];
    static char[] a = new char[N];
    static char[] b = new char[N];
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        String s1 = scan.next();
        n = s1.length();
        for(int i = 1;i <= n;i ++) a[i] = s1.charAt(i - 1);
        String s2 = scan.next();
        m = s2.length();
        for(int i = 1;i <= m;i ++) b[i] = s2.charAt(i - 1);
        for(int i = 1;i <= n;i ++)
            for(int j = 1;j <= m;j ++)
            {
                f[i][j] = Math.max(f[i - 1][j],f[i][j - 1]);
                if(a[i] == b[j])
                    f[i][j] = Math.max(f[i][j], f[i - 1][j - 1] + 1);
            }
        System.out.println(f[n][m]);
    }
}

2、回文串

算法分析

区间dp

从当前样子变成初始状态需要添加字母的数量 等价于 当前样子变成最大的回文串需要剪去的字母的数量
即至少减去多少字母 等价于 总数量 - 最大回文子序列的长度

状态计算的选择方式和最长公共子序列类似

dbeb2ca84e7ee6b21319802cbd0170d.png

时间复杂度 O(n^2)

Java 代码

import java.util.Scanner;

public class Main {
    static int N = 1010;
    static int[][] f = new int[N][N];
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        String s = scan.next();
        int n = s.length();
        for(int len = 1;len <= n;len ++)
        {
            for(int i = 0;i + len - 1 < n;i ++)
            {
                int j = i + len - 1;

                if(len == 1) f[i][j] = 1;
                else
                {
                    f[i][j] = Math.max(f[i][j - 1], f[i + 1][j]);
                    if(s.charAt(i) == s.charAt(j)) f[i][j] = Math.max(f[i][j], f[i + 1][j - 1] + 2);
                }
            }
        }
        System.out.println(n - f[0][n - 1]);
    }
}

3、蒜头君的日志

算法分析

题目抽象出来是一个最长公共上升子序列问题

image.png

优化:
由于状态转移时每次需要用到前缀的信息计算出来的信息(最大值),因此在枚举a[]数组每个元素时,用maxv记录当前a[i] > 所有b[k]时,f[k] + 1的最大值,其中k < j,可以降到二维的复杂度

时间复杂度 O(n^3)

Java 代码1

import java.util.Scanner;

public class Main {
    static int N = 3010;
    static int[] a = new int[N];
    static int[] b = new int[N];
    static int[][] f = new int[N][N];
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        for(int i = 1;i <= n;i ++) a[i] = scan.nextInt();
        for(int i = 1;i <= n;i ++) b[i] = scan.nextInt();
        for(int i = 1;i <= n;i ++)
        {
            for(int j = 1;j <= n;j ++)
            {
                f[i][j] = f[i - 1][j];
                if(a[i] == b[j])
                {
                    f[i][j] = 1;//初始为1
                    for(int k = 1;k < j;k ++)
                    {
                        if(b[k] < b[j]) f[i][j] = Math.max(f[i][j], f[i - 1][k] + 1);
                    }
                }
            }
        }
        //需要类似最长上升子序列求得最大值,也可以直接加到上面的循环中
        int res = 0;
        for(int i = 1;i <= n;i ++) res = Math.max(res,f[n][i]);
        System.out.println(res);
    }
}

时间复杂度 O(n^2)

Java 代码2

import java.util.Scanner;

public class Main {
    static int N = 3010;
    static int[] a = new int[N];
    static int[] b = new int[N];
    static int[][] f = new int[N][N];
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        for(int i = 1;i <= n;i ++) a[i] = scan.nextInt();
        for(int i = 1;i <= n;i ++) b[i] = scan.nextInt();
        for(int i = 1;i <= n;i ++)
        {
            int maxv = 1;//记录当前a[i] > 所有b[k]时,f[k] + 1的最大值,其中k < j
            for(int j = 1;j <= n;j ++)
            {
                f[i][j] = f[i - 1][j];
                if(a[i] == b[j]) f[i][j] = maxv;
                if(b[j] < a[i]) maxv = Math.max(maxv, f[i][j] + 1);
            }
        }
        //需要类似最长上升子序列求得最大值,也可以直接加到上面的循环中
        int res = 0;
        for(int i = 1;i <= n;i ++) res = Math.max(res,f[n][i]);
        System.out.println(res);
    }
}

4、蒜头君的密码文件

算法分析

最短编辑距离


image.png

时间复杂度O(n^2)

Java 代码

import java.util.Scanner;

public class Main {
    static int N = 1010;
    static int[][] f = new int[N][N];
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        String s1 = " " + scan.next();
        String s2 = " " + scan.next();
        int n = s1.length() - 1;
        int m = s2.length() - 1;
        for(int i = 0;i <= n;i ++) f[i][0] = i;
        for(int i = 0;i <= m;i ++) f[0][i] = i;
        for(int i = 1;i <= n;i ++)
            for(int j = 1;j <= m;j ++)
            {
                f[i][j] = Math.min(f[i - 1][j] + 1, f[i][j - 1] + 1);
                if(s1.charAt(i) == s2.charAt(j)) f[i][j] = Math.min(f[i][j], f[i - 1][j - 1]);
                else f[i][j] = Math.min(f[i][j], f[i - 1][j - 1] + 1);
            }
        System.out.println(f[n][m]);
    }
}

相关文章

  • 动态规划

    1、求最长公共子序列 2、求最长公共子串 3、0-1背包问题 4、最短编辑距离

  • 动态规划常见面试题

    子序列类型编辑距离 最长递增子序列 最大子数组 最长公共子序列 背包问题0-1背包问题 子集背包问题 完全背包问题...

  • 最长公共子序列和最长公共子串

    最长公共子序列和最长公共子串区别 最长公共子串(Longest CommonSubstring)和最长公共子序列(...

  • 公共子序列问题

    最长公共子序列 最长上升子序列 最长公共上升子序列

  • 算法(04)动态规划

    零钱问题 背包问题 最长公共子序列 最长公共子串 最长上升子序列 最大连续子序列和

  • LCS问题

    LCS问题包括最长公共子序列和最长公共子串,其中,最长公共子串要求必须连续。 对于二者的求解方式 最长公共子序列:...

  • 第22章 最长公共子序列和编辑距离

    1、最长公共子序列 算法分析 时间复杂度 Java 代码 2、回文串 算法分析 区间dp 从当前样子变成初始状态需...

  • 算法问题清单

    最大子序列和最长公共子序列最长公共子串大整数相乘/除/加数组最大乘积

  • 每天一道算法题18

    【最长公共子序列,子串】给定两个字符串上str1 和 str2, 求两个字符的最长公共子序列和最长公共子串。 最长...

  • 子序列问题

    最长公共子序列 最长上升/下降/不升/不降子序列

网友评论

      本文标题:第22章 最长公共子序列和编辑距离

      本文链接:https://www.haomeiwen.com/subject/opaluhtx.html