【动态规划】最长公共子串
题目
应用 1:最长公共子串
题目
给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子串的长度。如果不存在 公共子串 ,返回 0 。
示例 1:
输入:text1 = "abcbcde", text2 = "bbcbce"
输出:4
解释:最长公共子串是 "bcbc" ,它的长度为 4 。
解题思路
我们使用动态规划求解,设
这里,我们假设字符串
边界条件
显然,当其中一个数组长度为零时,它们的公共前缀为零,因此,初始条件为:
状态转移
当两个字符串的长度大于
-
如果
,那么,当前状态可以由前一个状态转移得到,此时,公共子串的长度较上一个状态增加了一个字符的长度; -
如果
,那么,以字符 和字符 结尾的子串没有公共前缀,此时,它们的最长公共子串长度为零。
因此,状态转移方程为:
代码实现
class Solution { public int LongestCommonSubStr(String text1, String text2) { int m = text1.length(), n = text2.length(); int[][] dp = new int[m + 1][n + 1]; int result = 0; for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (text1.charAt(i - 1) == text2.charAt(j - 1)) { dp[i][j] = dp[i - 1][j - 1] + 1; } else { dp[i][j] = 0; } result = Math.max(result, dp[i][j]); } } return result; } }
应用 2:Leetcode 718. 最长重复子数组
题目
解题思路
代码实现
给两个整数数组 nums1 和 nums2 ,返回 两个数组中 公共的 、长度最长的子数组的长度 。
示例 1:
输入:nums1 = [1,2,3,2,1], nums2 = [3,2,1,4,7]
输出:3
解释:长度最长的公共子数组是 [3,2,1] 。
解题思路
方法一:动态规划
注意,这里的子数组是连续的子数组。
这里,我们假设数组
同时,假设
初始条件
显然,当其中一个数组长度为零时,它们的公共前缀为零,因此,初始条件为:
状态转移
当字符长度大于零时,我们可以考虑枚举其中一个数组的前缀,这里假设枚举前缀
即对于子数组
-
如果数字
与数字 相等,那么,它们显然可以构成更长的数组前缀; -
如果它们不相等,那么,它们的公共前缀就为零。
因此,状态转移方程为:
复杂度
-
时间复杂度:
-
空间复杂度:
方法二:滑动窗口
我们考虑使用滑动窗口的思路求解,我们以其中一个数组为基准,枚举它的起始位置,并求解它与另一个数组的最长公共前缀。
复杂度
-
时间复杂度:
-
空间复杂度:
代码实现
- 方法一
class Solution { public int findLength(int[] nums1, int[] nums2) { int m = nums1.length, n = nums2.length; int[][] dp = new int[m + 1][n + 1]; int result = 0; for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (nums1[i - 1] == nums2[j - 1]) { dp[i][j] = dp[i - 1][j - 1] + 1; } else { dp[i][j] = 0; } result = Math.max(result, dp[i][j]); } } return result; } }
- 方法二
class Solution { public int findLength(int[] nums1, int[] nums2) { int n = nums1.length, m = nums2.length; int result = 0; for (int i = 0; i < n; i++) { int length = Math.min(m, n - i); int maxLength = getMaxLength(nums1, nums2, i, 0, length); result = Math.max(result, maxLength); } for (int i = 0; i < m; i++) { int length = Math.min(n, m - i); int maxLength = getMaxLength(nums1, nums2, 0, i, length); result = Math.max(result, maxLength); } return result; } private int getMaxLength(int[] a, int[] b, int i, int j, int length) { int result = 0, count = 0; for (int k = 0; k < length; k++) { if (a[i + k] == b[j + k]) { count++; } else { count = 0; } result = Math.max(result, count); } return result; } }
本文作者:LARRY1024
本文链接:https://www.cnblogs.com/larry1024/p/18007566
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步