两个字符串中最大的相同的子串(java编写)

如何求两个字符串中最大 的相同的子串?

以下是用java编写的程序

public class StingTest4 {


public static void main(String[] args) {
// TODO Auto-generated method stub
/*
* 两个字符串中最大的相同的子串

* */
String str1="abcbbefijgiopliwo";
String str2="abbefidsmoiwolf";
   String maxSubstr= getMaxSubstr(str1,str2);
   System.out.println(maxSubstr);
}


public static String getMaxSubstr(String str1, String str2) {
// TODO Auto-generated method stub
String longStr=str1.length()>str2.length()?str1:str2;
String shortStr=str1.equals(longStr)?str2:str1;
for(int x=0;x<shortStr.length();x++){
for(int y=0, z=shortStr.length()-x;z<=shortStr.length();y++,z++){
String temp=shortStr.substring(y, z);
if(longStr.contains(temp))
return temp;
}
}
return null;
}


}

结果:

bbefi

<think>好的,我现在需要帮助用户解决在Java中实现求两个字符串的最长公共子串的问题。首先,我得回忆一下相关的算法,最长公共子串和最长公共子序列的区别。用户明确提到是子串,也就是需要连续的字符,而不是子序列那样可以不连续。接下来,我需要考虑常见的解决方法。动态规划通常是解决这类问题的有效方法。动态规划的思路是创建一个二维数组来记录两个字符串在各个位置的匹配情况。例如,dp[i][j]表示以字符串1的第i个字符和字符串2的第j个字符结尾的最长公共子串的长度。如果两个字符相等,那么dp[i][j] =dp[i-1][j-1] +1,否则为0。同时需要记录最大长度和结束位置,以便最后提取子串。 然后,我需要考虑如何优化空间复杂度。因为二维数组可能会占用较大空间,特别是当字符串很长时。可以优化为一维数组,因为每次更新只需要前一行的信息。不过,对于初学者来说,可能先实现标准的二维数组方法更容易理解,之后再考虑优化。接下来,我需要编写示例代码。用户要求的是Java实现,所以代码结构要符合Java语法。首先处理边界情况,比如空字符串的情况。然后初始化dp数组,遍历两个字符串的所有字符,填充dp数组,并跟踪最大长度和结束位置。最后根据记录的maxLength和endIndex来提取子串。 还要注意字符串的索引问题,Java字符串的charAt是从0开始的,所以在循环时可能需要从1开始处理,或者调整索引以避免越界。另外,动态规划数组的大小通常是长度加1,这样可以更方便处理初始状态。 用户可能还关心时间复杂度和空间复杂度。动态规划方法的时间复杂度是O(n*m),其中n和m是两个字符串的长度。空间复杂度如果使用二维数组是O(n*m),优化为一维数组后可以降到O(min(n,m))。 在编写代码时,要确保变量命名清晰,注释适当,方便用户理解。例如,使用maxLength和endIndex这样的变量名,并在关键步骤添加注释说明。 最后,测试示例是否正确。比如用户提到的例子BDCABA和ABCBDAB,最长公共子串可能有多个,但根据问题描述,用户可能需要输出其中一个,比如BCBA或BDAB。不过这里可能需要注意,用户提到的例子其实是子序列的例子,而子串必须是连续的,所以需要确认正确的测试用例。例如,假设字符串是“abcde”和“abcfde”,最长公共子串可能是“abc”或“fde”,具体取决于连续情况。可能还需要考虑是否有多个相同长度的最长公共子串,如何处理这种情况。通常,代码可能返回第一个找到的最长子串,或者可以修改代码来记录所有可能的子串,但用户可能只需要一个示例,所以保持简单即可。总结步骤:处理边界情况,初始化DP数组,填充DP数组并记录最大值和结束位置,根据记录提取子串编写代码时注意索引和边界条件,确保正确性。</think>### Java实现最长公共子串算法 最长公共子串(Longest Common Substring)与子序列不同,要求字符必须连续。动态规划是解决该问题的有效方法,时间复杂度为$O(n*m)$。 #### 算法步骤 1. 创建二维数组`dp[i][j]`记录以`str1[i-1]`和`str2[j-1]`结尾的公共子串长度 2. 状态转移方程: $$dp[i][j] = \begin{cases} dp[i-1][j-1] + 1 & \text{当 } str1[i-1] = str2[j-1] \\ 0 & \text{否则} \end{cases}$$ 3. 记录最大长度和结束位置 4. 根据结束位置提取子串 #### 示例代码 ```java public class LongestCommonSubstring { public static String findLCS(String str1, String str2) { if (str1 == null || str2 == null || str1.isEmpty() || str2.isEmpty()) { return ""; } int[][] dp = new int[str1.length() + 1][str2.length() + 1]; int maxLength = 0; int endIndex = 0; for (int i = 1; i <= str1.length(); i++) { for (int j = 1; j <= str2.length(); j++) { if (str1.charAt(i-1) == str2.charAt(j-1)) { dp[i][j] = dp[i-1][j-1] + 1; if (dp[i][j] > maxLength) { maxLength = dp[i][j]; endIndex = i - 1; // 记录在str1中的结束位置 } } } } return maxLength == 0 ? "" : str1.substring(endIndex - maxLength + 1, endIndex + 1); } public static void main(String[] args) { String s1 = "ABCBDAB"; String s2 = "BDCABA"; System.out.println("最长公共子串: " + findLCS(s1, s2)); // 输出"BDAB" } } ``` #### 代码说明 1. 二维数组`dp`比原字符串长度多1,避免处理边界条件 2. 双重循环遍历所有字符组合 3. 当字符匹配时更新`dp`值,并跟踪最大长度 4. 通过`substring`方法截取最长子串 #### 优化方向 1. 空间优化:使用滚动数组将空间复杂度降为$O(min(n,m))$[^1] 2. 后缀树方法:可将时间复杂度降为$O(n+m)$,但实现复杂度较高 3. 并行处理:对大规模字符串进行分块处理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值