求两个字符串的最大公共子串
在计算机科学中,找到两个字符串的最大公共子串是一个常见的问题。我们可以通过动态规划的方式来解决这个问题。下面,我将为刚入行的小白详细解释如何实现这个功能。
整体流程
为了清晰地展示整个实现过程,我们可以将其分为以下几个步骤:
步骤 | 描述 |
---|---|
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_length
和end_pos
。这使得我们可以在一个步骤中完成这一部分。
第四步:根据最大子串的信息提取子串
根据end_pos
和max_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实现求两个字符串的最大公共子串的功能。希望这篇文章能帮助你更好地理解动态规划的基本思路。同时,也鼓励你动手实现并试着扩展这个算法,比如考虑重复子串的个数,或是修改为求公共前缀等。编程的乐趣在于实践,探索出无数的可能性让我们不断成长。继续加油!