求两个字符串的最大公共子串

在计算机科学中,找到两个字符串的最大公共子串是一个常见的问题。我们可以通过动态规划的方式来解决这个问题。下面,我将为刚入行的小白详细解释如何实现这个功能。

整体流程

为了清晰地展示整个实现过程,我们可以将其分为以下几个步骤:

步骤 描述
1 初始化一个二维数组
2 填充二维数组
3 找到最大子串的长度及结束位置
4 根据最大子串的信息提取子串
5 返回子串

每一步的详细实现

第一步:初始化一个二维数组

我们需要定义一个二维数组来存放字符串的比较结果。我们为两个字符串创建一个大小为 (m+1)x(n+1) 的数组,其中 m 和 n 分别是两个字符串的长度。这是因为我们需要一个额外的行和列来处理空字符串的情况。

def longest_common_substring(s1, s2):
    m, n = len(s1), len(s2)
    dp = [[0] * (n + 1) for _ in range(m + 1)]
    max_length = 0  # 最大子串的长度
    end_pos = 0     # 最大子串结束的位置

第二步:填充二维数组

使用双重循环遍历两个字符串的字符,进行比较。如果字符相同,则在二维数组中相应位置加1;如果不同,则该位置为0。

    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if s1[i - 1] == s2[j - 1]:
                dp[i][j] = dp[i - 1][j - 1] + 1  # 如果匹配,长度加1
                if dp[i][j] > max_length:
                    max_length = dp[i][j]  # 更新最大长度
                    end_pos = i  # 更新结束的位置
            else:
                dp[i][j] = 0  # 不匹配则长度为0

第三步:找到最大子串的长度及结束位置

在构建过程中,我们已经在上一步更新了max_lengthend_pos。这使得我们可以在一个步骤中完成这一部分。

第四步:根据最大子串的信息提取子串

根据end_posmax_length的信息,我们可以提取到最大公共子串。

    longest_substring = s1[end_pos - max_length:end_pos]

第五步:返回子串

最后,我们将提取到的子串返回。

    return longest_substring

完整函数

将以上步骤汇总,得到完整的求最大公共子串的函数:

def longest_common_substring(s1, s2):
    m, n = len(s1), len(s2)
    dp = [[0] * (n + 1) for _ in range(m + 1)]
    max_length = 0  # 最大子串的长度
    end_pos = 0     # 最大子串结束的位置

    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if s1[i - 1] == s2[j - 1]:
                dp[i][j] = dp[i - 1][j - 1] + 1  # 如果匹配,长度加1
                if dp[i][j] > max_length:
                    max_length = dp[i][j]  # 更新最大长度
                    end_pos = i  # 更新结束的位置
            else:
                dp[i][j] = 0  # 不匹配则长度为0

    longest_substring = s1[end_pos - max_length:end_pos]
    return longest_substring

旅行图

我们可以用 Mermaid 语法绘制出一个简单的旅行图,展示从输入字符串到输出最大公共子串的过程。

journey
    title 从字符串到公共子串的旅程
    section 输入
      输入字符串1: 5: 存储
      输入字符串2: 5: 存储
    section 处理
      初始化二维数组: 3: 移动
      填充二维数组: 7: 移动
      查找最大长度与结束位置: 4: 移动
      提取最大公共子串: 5: 移动
    section 输出
      返回最大公共子串: 2: 到达

状态图

我们同样可以用 Mermaid 语法展示状态图,清晰地展示每一步的状态转变:

stateDiagram
    [*] --> 初始化
    初始化 --> 填充
    填充 --> 查找最大长度
    查找最大长度 --> 提取子串
    提取子串 --> [*]

结论

通过以上步骤,我们详细讲解了如何使用Python实现求两个字符串的最大公共子串的功能。希望这篇文章能帮助你更好地理解动态规划的基本思路。同时,也鼓励你动手实现并试着扩展这个算法,比如考虑重复子串的个数,或是修改为求公共前缀等。编程的乐趣在于实践,探索出无数的可能性让我们不断成长。继续加油!