Java最长公共子序列示例源码

Java最长公共子序列示例源码可以用于找到两个字符串之间的最长公共子序列。以下是Java最长公共子序列示例源码的完整攻略:

1. 题目描述

给定两个字符串s1s2,找到它们的最长公共子序列(LCS)。

2. 示例

示例1:

输入:s1 = "abcde", s2 = "ace" 
输出:3  
解释:最长公共子序列是 "ace",它的长度是3。

示例2:

输入:s1 = "abc", s2 = "abc"
输出:3
解释:最长公共子序列是 "abc",它的长度是3。

3. 解法分析

在这个问题中,我们可以使用动态规划的方法来解决。

如果我们定义一个二维数组dp[i][j]来表示s1s2中前i个和前j个字符的LCS长度,那么我们可以考虑以下几种情况:

  1. 如果s1[i-1]s2[j-1]相同,那么它们肯定在LCS中。此时,dp[i][j] = dp[i-1][j-1] + 1
  2. 如果s1[i-1]s2[j-1]不同,则它们可能不在LCS中,此时我们需要选择跳过s1[i-1]或者s2[j-1],哪种选择能让LCS最长,就选哪种。因此,dp[i][j] = max(dp[i-1][j], dp[i][j-1])

最终,dp[s1.length()][s2.length()]表示的就是s1s2的LCS长度。

4. 代码实现

public int longestCommonSubsequence(String s1, String s2) {
    int m = s1.length(), n = s2.length();
    int[][] dp = new int[m + 1][n + 1];
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
                dp[i][j] = dp[i - 1][j - 1] + 1;
            } else {
                dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
            }
        }
    }
    return dp[m][n];
}

5. 示例说明

示例1

输入的两个字符串是 "abcde""ace"。我们使用二维数组dp来表示它们之间的LCS长度。

初始化的时候,dp[0][0]表示空字符串的LCS长度为0,那么 dp[0][j]dp[i][0] 也必须都为0,因此 dp 数组的第一行和第一列都初始化为0。

  a   c   e
a 0   0   0
b 0   0   0
c 0   1   1
d 0   1   1
e 0   1   2

我们可以看到,当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数组中,例如dp[3][1]s1[2]s2[0]不同,则它们可能不在LCS中,此时我们需要选择跳过s1[2]或者s2[0],哪种选择能让LCS最长,就选哪种。: dp[3][1] = max(dp[2][1], dp[3][0]) = max(1, 0) = 1

最终dp[s1.length()][s2.length()]的值就是3,即s1s2的LCS长度。

示例2

输入的两个字符串是 "abc""abc"

初始化的时候,dp[0][0]表示空字符串的LCS长度为0,那么 dp[0][j]dp[i][0] 也必须都为0,因此 dp 数组的第一行和第一列都初始化为0。

  a   b   c
a 0   0   0
b 0   1   1
c 0   1   2

同样的,我们可以看到,当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[s1.length()][s2.length()]的值就是3,即s1s2的LCS长度。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java最长公共子序列示例源码 - Python技术站

(0)
上一篇 2023年5月27日
下一篇 2023年5月27日

相关文章

  • 极致体验ajax局部和整体刷新

    极致体验ajax局部和整体刷新攻略 什么是ajax局部和整体刷新 ajax是一种可以通过JavaScript向服务器发起异步请求并更新页面内容的技术。在传统web页面中,每一次用户操作请求都会导致整个页面重新加载,而使用ajax局部刷新技术可以仅刷新需要改变的部分,提高了用户体验。 整体刷新指的是重新加载整个页面,这种方式操作简单但是页面需要重新加载一遍,时…

    Java 2023年6月16日
    00
  • Spring mvc文件上传下载代码实例

    Spring MVC文件上传下载代码实例 在Web应用程序中,文件上传和下载是常见的功能。Spring MVC提供了方便的API来处理文件上传和下载。本文将介绍如何在Spring MVC中实现文件上传和下载,并提供两个示例说明。 文件上传 步骤一:配置文件上传 首先,我们需要在spring-servlet.xml文件中配置文件上传。可以通过添加以下配置来实现…

    Java 2023年5月17日
    00
  • Redis Plus 来了,性能炸裂!

    来源:https://developer.aliyun.com/article/705239 1 什么是KeyDB? KeyDB是Redis的高性能分支,专注于多线程,内存效率和高吞吐量。除了多线程之外,KeyDB还具有仅在Redis Enterprise中可用的功能,例如Active Replication,FLASH存储支持以及一些根本不可用的功能,例如…

    Java 2023年4月25日
    00
  • SpringBoot自定义注解API数据加密和签名校验

    首先我想说明一下本次攻略的目的和背景。随着网络技术的快速发展,很多 web 应用都包含了用户敏感信息,数据的安全性也变得越来越重要。而其中一个解决方案就是加密和签名校验。SpringBoot 作为一个主流的开发框架,提供了各种扩展点,开发人员可以通过自定义注解来实现各种功能,其中就包括 API 数据加密和签名校验。我们的攻略就是基于 SpringBoot 自…

    Java 2023年5月20日
    00
  • 基于Spring-Security自定义登陆错误提示信息

    基于Spring-Security自定义登陆错误提示信息的完整攻略如下: 第一步:添加Spring-Security依赖 我们需要在Maven或者Gradle项目中添加Spring-Security依赖,在pom.xml或build.gradle中添加相应的依赖配置,例如: <dependency> <groupId>org.spri…

    Java 2023年5月20日
    00
  • spring中IOC控制反转依赖注入和new对象的区别说明

    下面是关于“spring中IOC控制反转依赖注入和new对象的区别说明”的完整攻略。 控制反转(IoC) 控制反转,即IoC(Inversion of Control),是一种将程序的控制权从调用者转移至被调用者的设计模式。在传统的编程模式中,客户端程序通常需要直接创建和管理对象,并通过其接口调用其方法来完成所需的业务逻辑。而在IoC模式中,对象的创建和管理…

    Java 2023年5月26日
    00
  • 图文详解Java线程和线程池

    图文详解Java线程和线程池 什么是线程 线程是操作系统能够进行运算调度的最小单位。一个进程可以包含多个线程,线程共享进程资源,但是是CPU分配资源的独立单位。 Java中的线程 Java中的线程是使用Thread类对象来创建。Java中的线程有以下几种状态:新建状态、可运行状态、阻塞状态和死亡状态。在Java中,实现多线程有两种方式,一是继承Thread类…

    Java 2023年5月18日
    00
  • Java8之Lambda表达式使用解读

    Java8之Lambda表达式使用解读 什么是Lambda表达式? Lambda表达式是一种匿名函数,它没有名称,但它有参数列表、函数体和可能存在的返回类型,可以在需要函数类型的上下文中使用。 举个例子,我们可以使用Lambda表达式来实现简化的Runnable接口: Runnable r = () -> System.out.println(&quo…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部