【LeetCode】最长公共子串&最长公共子序列

本文介绍了如何使用动态规划解决LeetCode中的最长公共子串和子序列问题。通过分析状态转移方程,阐述了动态规划的步骤,并提供了具体的解题思路和初始化过程。对于找到最长公共子串,可以通过dp数组找到重复子数组的边界;而对于最长公共子序列,即使字符不连续,仍可以找到最大长度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

子序列与子串的区别:

假设有S1 = “abcdeffg” S2 = "abcfg"
子串:“abc”
子序列:“abcfg”

简单的说,子串就是需要连续,子序列不需要连续。

题目1:子串

可能我这么说不严谨,其实718题是子数组,但意思是一样的,都是需要找连续的。

718. 最长重复子数组

给两个整数数组 A 和 B ,返回两个数组中公共的、长度最长的子数组的长度。

示例 1:

输入:
A: [1,2,3,2,1]
B: [3,2,1,4,7]
输出: 3
解释: 
长度最长的公共子数组是 [3, 2, 1]。


说明:

1 <= len(A), len(B) <= 1000
0 <= A[i], B[i] < 100

题解:

分析:我们可以用动态规划来做。

动态规划步骤1:定义状态

我们有两个数组,我们要找他们的最长公共子数组的长度,那么状态如下:

dp(i,j):表示A数组中以[i]结尾的子数组与B数组中以[j]结尾的子数组的最长长度。

动态规划步骤2:找到状态转移方程

如果说A[i] == B[j],那说明我们在这个两个位置上,是有公共部分的,所以我们的状态应该基于前一个状态 dp(i - 1, j - 1) + 1 

那如果A[i] != B[j],说明在这个位置上没有公共部分,取0;

<
### Java 实现最长公共子串 LeetCode 题解 对于寻找两个字符串之间的最长公共子串问题,在处理过程中通常采用动态规划方法来解决。该算法通过构建一个二维数组 `dp` 来记录两个字符串之间字符匹配的情况。 具体来说,当遍历到 `text1[i-1] == text2[j-1]` 时,则有 `dp[i][j] = dp[i-1][j-1] + 1` 表明当前字符相等并延续之前的连续相同字符计数;如果不相等则设置为零因为这里关注的是连续相同的子串而非子序列[^1]。 下面是一个完整的解决方案: ```java class Solution { public String longestCommonSubstring(String str1, String str2) { int m = str1.length(); int n = str2.length(); // 创建DP表 int[][] dp = new int[m + 1][n + 1]; // 记录最大长度及其结束位置 int maxLength = 0; int endIndex = -1; for (int i = 1; i &lt;= m; ++i){ char c1 = str1.charAt(i - 1); for (int j = 1; j &lt;= n; ++j){ char c2 = str2.charAt(j - 1); if(c1 == c2){ dp[i][j] = dp[i - 1][j - 1] + 1; if(dp[i][j] &gt; maxLength){ maxLength = dp[i][j]; endIndex = i - 1; } }else{ dp[i][j] = 0; } } } // 如果找到了有效结果就截取出来作为最终答案 return maxLength != 0 ? str1.substring(endIndex - maxLength + 1,endIndex + 1): &quot;&quot;; } } ``` 此代码实现了上述逻辑,并能够有效地找出给定两字符串间的最长公共子串。注意这里的实现方式与最长公共子序列不同之处在于一旦遇到不匹配即重置计数值为零以确保只考虑连续部分[^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值