Java 中找到两个字符串的最长公共子串

在开发中,字符串操作是非常常见的需求之一。特别是在处理文本数据时,找到两个字符串中的最长公共子串是一项重要的任务。本文将介绍如何使用 Java 实现这一功能。

整体流程

我们将通过动态规划的方式找到最长公共子串。整个过程可以拆分为以下几个步骤:

步骤 描述
1 定义方法,接受两个字符串作为参数。
2 初始化额外的二维数组用于动态规划。
3 使用双重循环填充数组,通过比较字符实现动态规划。
4 在填充数组的过程中,记录最长公共子串的长度和结束位置。
5 根据记录的信息从原始字符串中提取出最长公共子串。
6 返回最长公共子串的结果。

详细步骤分析

1. 定义方法

首先,我们需要定义一个方法,该方法接受两个字符串作为参数。

public class LongestCommonSubstringFinder {
    /**
     * 查找两个字符串的最长公共子串
     * @param str1 第一个字符串
     * @param str2 第二个字符串
     * @return 最长公共子串
     */
    public String longestCommonSubstring(String str1, String str2) {
        // 接下来的逻辑将在此处实现
    }
}

2. 初始化动态规划数组

我们需要一个二维数组来存储匹配信息,数组的大小取决于两个字符串的长度。

int[][] dp = new int[str1.length() + 1][str2.length() + 1];

dp[i][j] 将表示以 str1[i-1]str2[j-1] 结尾的最长公共子串的长度。

3. 填充动态规划数组

使用双重循环遍历两个字符串,更新dp数组。

int maxLength = 0; // 记录最长公共子串的长度
int endIndex = 0;  // 记录最长公共子串在str1中的结束位置

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; // 记录结束位置
            }
        }
    }
}

4. 提取最长公共子串

根据记录的结束位置和最长长度,我们可以从 str1 中提取出最长公共子串。

String longestSubstring = str1.substring(endIndex - maxLength, endIndex);

5. 返回最终结果

现在,我们已经获得了最长公共子串,可以将其返回。

return longestSubstring;

完整代码示例

以下是整个方法的完整实现,包括上述所有步骤:

public class LongestCommonSubstringFinder {
    /**
     * 查找两个字符串的最长公共子串
     * @param str1 第一个字符串
     * @param str2 第二个字符串
     * @return 最长公共子串
     */
    public String longestCommonSubstring(String str1, String str2) {
        int[][] dp = new int[str1.length() + 1][str2.length() + 1];
        int maxLength = 0; // 记录最长公共子串的长度
        int endIndex = 0;  // 记录最长公共子串在str1中的结束位置
        
        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; // 记录结束位置
                    }
                }
            }
        }
        
        // 最长公共子串
        return str1.substring(endIndex - maxLength, endIndex);
    }
}

序列图

以下是调用 longestCommonSubstring 方法时的序列图:

sequenceDiagram
    participant User
    participant LongestCommonSubstringFinder
    
    User->>LongestCommonSubstringFinder: longestCommonSubstring(str1, str2)
    LongestCommonSubstringFinder->>LongestCommonSubstringFinder: Initialize dp array
    LongestCommonSubstringFinder->>LongestCommonSubstringFinder: Fill dp array
    LongestCommonSubstringFinder->>LongestCommonSubstringFinder: Extract longest substring
    LongestCommonSubstringFinder-->>User: Return longest substring

总结

通过以上步骤,我们实现了一个能够找到两个字符串中最长公共子串的 Java 方法。掌握动态规划的思维方式,可以极大增强解决字符串问题的能力。希望本文能够帮助刚入行的小白们更好理解和实现这一功能。如果有任何疑问,请随时提问!