动态规划——多样本位置全对应的尝试模型,两个字符串的最长公共子序列问题

简介: 动态规划——多样本位置全对应的尝试模型,两个字符串的最长公共子序列问题

题目

给定两个字符串str1和str2,str1="a123bc",str2="12dea3f"。那么这两个字符串的最长公共子序列的长度是多少?

很明显,根据这个题目的类型再加上我们以往的经验,我们可以根据题目给出的两个样本做出一个二维表:

int[][] dp=new int[str1.length][str2.length];

在这里插入图片描述
那么,这个表的含义是什么呢?

表中任意一个格子(dpi),就代表str1[0]到str1[i]和str2[0]到str2[j]的最长公共子序列的长度是多少。因为我们要求的问题是两个字符串的整体的最长公共子序列有多长。

那么把右下角的格子算出来就是我们要求的主问题。

在这里插入图片描述
记住这一点:dpi代表str1[0]到str1[i]和str2[0]到str2[j]的最长公共子序列的长度!!!

1)填dp0的值,两个字符串都只拿第一个字符比较,相同就说明最长公共子序列长度为1;否则为0

dp[0][0]=str1[0]==str2[0]?1:0;

2)填第0行数据:str1只拿第一个字符,和str2整体比较

for(int j=1; j<str2.length; j++) {
    dp[0][j]=Math.max(dp[0][j-1], str2[j]==str1[0]?1:0);
}

3)填第0列数据:str2只拿第一个字符,和str1整体比较

for(int i=1; i<str1.length; i++) {
    dp[i][0]=Math.max(dp[i-1][0],str1[i]==str2[0]?1:0);
}

在这里插入图片描述
接下来,任何普遍位置如何尝试呢?有4种可能性:

1)两个字符串的最长公共子序列既不以str1[i]结尾,也不以str2[j]结尾,比如"a123b"和"c123e"的最长公共子序列是"123"。也就是说,str1[0]到str1[i]和str2[0]到str2[j]的最长公共子序列的长度等同于str1[0]到str1[i-1]和str2[0]到str2[j-1]的最长公共子序列的长度。也即是说,任何一个普遍位置的格子有可能依赖其左上角的格子!!!
在这里插入图片描述

2)两个字符串的最长公共子序列以str1[i]结尾,但是不以str2[j]结尾,比如"ab123"和"c123ef"的最长公共子序列是"123"。也就是说,str1[0]到str1[i]和str2[0]到str2[j]的最长公共子序列的长度等同于str1[0]到str1[i]和str2[0]到str2[j-1]的最长公共子序列的长度。也即是说,任何一个普遍位置的格子有可能依赖其左边的格子!!!
在这里插入图片描述
3)两个字符串的最长公共子序列不以str1[i]结尾,但是以str2[j]结尾,比如"a123bc"和"ef123"的最长公共子序列是"123"。也就是说,str1[0]到str1[i]和str2[0]到str2[j]的最长公共子序列的长度等同于str1[0]到str1[i-1]和str2[0]到str2[j]的最长公共子序列的长度。也即是说,任何一个普遍位置的格子有可能依赖其右上角的格子!!!
在这里插入图片描述
4)两个字符串的最长公共子序列既以str1[i]结尾,也以str2[j]结尾,比如"ab12c3"和"d12ef3"的最长公共子序列是"123"。但是前提条件必须是str1[i]==str2[j]。也就是说,str1[0]到str1[i]和str2[0]到str2[j]的最长公共子序列的长度等同于str1[0]到str1[i-1]和str2[0]到str2[j-1]的最长公共子序列的长度再加1!!!

除此以外,再无其它可能性。这种可能性组织方式的关键是最长公共子序列最后一个字符在哪个位置。

完整代码:

package com.harrison.class13;

public class Code08_LongestCommonSubsequence {
    public static int lcs(char[] str1,char[] str2) {
        int[][] dp=new int[str1.length][str2.length];
        dp[0][0]=str1[0]==str2[0]?1:0;
        // 填第0列的值
        for(int i=1; i<str1.length; i++) {
            dp[i][0]=Math.max(dp[i-1][0],str1[i]==str2[0]?1:0);
        }
        // 填第0行的值
        for(int j=1; j<str2.length; j++) {
            dp[0][j]=Math.max(dp[0][j-1], str2[j]==str1[0]?1:0);
        }
        for(int i=1; i<str1.length; i++) {
            for(int j=1; j<str2.length; j++) {
                dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
                // 如果if没中,为什么可能性1(dp[i-1][j-1])可以省略
                // 因为可能性2和3必然会覆盖可能性1
                if(str1[i]==str2[j]) {
                    dp[i][j]=Math.max(dp[i][j], dp[i-1][j-1]+1);
                }
            }
        }
        return dp[str1.length-1][str2.length-1];
    }
    
    public static void main(String[] args) {
        System.out.println(lcs("a123bc".toCharArray(),"12dea3f".toCharArray()));
    }
}
相关文章
|
6月前
|
算法 测试技术 C++
【动态规划】【字符串】1092. 最短公共超序列
【动态规划】【字符串】1092. 最短公共超序列
|
5月前
|
存储 算法 数据可视化
LeetCode 132题详解:使用动态规划与中心扩展法解决分割回文串 II 的最少分割次数问题
LeetCode 132题详解:使用动态规划与中心扩展法解决分割回文串 II 的最少分割次数问题
|
5月前
|
算法
【经典LeetCode算法题目专栏分类】【第8期】滑动窗口:最小覆盖子串、字符串排列、找所有字母异位词、 最长无重复子串
【经典LeetCode算法题目专栏分类】【第8期】滑动窗口:最小覆盖子串、字符串排列、找所有字母异位词、 最长无重复子串
|
6月前
|
人工智能 自然语言处理 算法
【动态规划】【字符串】【前缀和】1639通过给定词典构造目标字符串的方案数
【动态规划】【字符串】【前缀和】1639通过给定词典构造目标字符串的方案数
|
6月前
|
算法 JavaScript 测试技术
动态规划 多源路径 字典树 LeetCode2977:转换字符串的最小成本
动态规划 多源路径 字典树 LeetCode2977:转换字符串的最小成本
|
6月前
|
算法 Java C++
数据结构与算法面试题:给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。(提示:使用动态规划或者中心扩散)
数据结构与算法面试题:给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。(提示:使用动态规划或者中心扩散)
83 0
|
6月前
|
算法 Java
给定一个字符串数组,如何找到其中最长的回文子串? 要求:编写一个Java函数,输入一个字符串数组,输出其中最长的回文子串。要求时间复杂度为O(n^2)。可以考虑使用动态规划或中心扩展的方法来优化算法。
给定一个字符串数组,如何找到其中最长的回文子串? 要求:编写一个Java函数,输入一个字符串数组,输出其中最长的回文子串。要求时间复杂度为O(n^2)。可以考虑使用动态规划或中心扩展的方法来优化算法。
85 1
|
6月前
动态规划解最长公共子序列(LCS)原理及模板
动态规划解最长公共子序列(LCS)原理及模板
55 0
|
6月前
|
算法 程序员 索引
【算法训练-动态规划 三】【双序列DP问题】最长重复子数组、最长公共子串、最长公共子序列、编辑距离
【算法训练-动态规划 三】【双序列DP问题】最长重复子数组、最长公共子串、最长公共子序列、编辑距离
104 0
|
机器学习/深度学习 搜索推荐 开发工具
对数据进行模糊匹配搜索(动态规划、最长公共子串、最长公共子序列)
倘若要在一堆数据中对一个关键词进行匹配搜索,传统做法是把数据拆分开,然后遍历他们,看看是否包含这个关键词,对于 “fin” 和 “finish” 这样存在包含关系的单词来说是没问题的,但是对于 “fish” 和 “finish” 这样并不存在包含关系的单词就失效了,这时候期望计算出两个单词的相似性,比如 “fish” 和 “finish” 都包含 “ish”,“ish” 的长度是 3,我们可以理解相似性为 3。目前主流做法是通过最长公共子串来寻找两个或多个已知字符串最长的子串。
134 0
对数据进行模糊匹配搜索(动态规划、最长公共子串、最长公共子序列)