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

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

题目

给定两个字符串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()));
    }
}
相关文章
|
存储 缓存 算法
带你读《存储漫谈Ceph原理与实践》第三章接入层3.1块存储 RBD(二)
《存储漫谈Ceph原理与实践》第三章接入层3.1块存储 RBD(二)
带你读《存储漫谈Ceph原理与实践》第三章接入层3.1块存储 RBD(二)
C语言文件流的饭卡管理系统
C语言文件流的饭卡管理系统
C语言文件流的饭卡管理系统
|
3天前
|
数据采集 人工智能 安全
|
13天前
|
云安全 监控 安全
|
4天前
|
自然语言处理 API
万相 Wan2.6 全新升级发布!人人都能当导演的时代来了
通义万相2.6全新升级,支持文生图、图生视频、文生视频,打造电影级创作体验。智能分镜、角色扮演、音画同步,让创意一键成片,大众也能轻松制作高质量短视频。
1085 152
|
18天前
|
机器学习/深度学习 人工智能 自然语言处理
Z-Image:冲击体验上限的下一代图像生成模型
通义实验室推出全新文生图模型Z-Image,以6B参数实现“快、稳、轻、准”突破。Turbo版本仅需8步亚秒级生成,支持16GB显存设备,中英双语理解与文字渲染尤为出色,真实感和美学表现媲美国际顶尖模型,被誉为“最值得关注的开源生图模型之一”。
1751 9
|
9天前
|
人工智能 自然语言处理 API
一句话生成拓扑图!AI+Draw.io 封神开源组合,工具让你的效率爆炸
一句话生成拓扑图!next-ai-draw-io 结合 AI 与 Draw.io,通过自然语言秒出架构图,支持私有部署、免费大模型接口,彻底解放生产力,绘图效率直接爆炸。
694 152
|
11天前
|
人工智能 安全 前端开发
AgentScope Java v1.0 发布,让 Java 开发者轻松构建企业级 Agentic 应用
AgentScope 重磅发布 Java 版本,拥抱企业开发主流技术栈。
660 14