📅  最后修改于: 2023-12-03 15:37:15.526000             🧑  作者: Mango
这是一道关于字符串处理的编程题,它要求我们找到两个字符串的最小公共子串,并返回它。
给定两个字符串 str1
和 str2
,请你找出它们的最小公共子串。如果两个字符串没有公共子串,则返回空字符串。
def find_shortest_common_substring(str1: str, str2: str) -> str:
pass
输入:
str1 = "abcdefgh"
str2 = "xbcdmn"
find_shortest_common_substring(str1, str2)
输出:
"bcd"
一种常见的思路是使用动态规划来解决这个问题。我们可以定义一个二维数组 dp
,其中 dp[i][j]
表示以 str1[i]
和 str2[j]
为结尾的两个子串的最长公共子串的长度。具体的转移方程如下:
dp[i][j] = dp[i-1][j-1] + 1 if str1[i] == str2[j] else 0
即如果 str1[i]
和 str2[j]
相等,则最长公共子串的长度为它们前面各自的子串的最长公共子串长度再加 1;否则最长公共子串的长度为 0。
在求解完 dp
数组之后,我们只需要找到其中的最大值,它就是二者的最长公共子串的长度。最后再通过二重循环来找到这个最长公共子串即可。
下面是基于动态规划的解法。代码注释中已经对每行代码进行了详细的解释。
def find_shortest_common_substring(str1: str, str2: str) -> str:
m, n = len(str1), len(str2)
dp = [[0] * n for _ in range(m)]
max_len, end_pos = 0, -1
for i in range(m):
for j in range(n):
if str1[i] == str2[j]:
if i == 0 or j == 0:
dp[i][j] = 1 # 第一行或第一列的情况
else:
dp[i][j] = dp[i-1][j-1] + 1 # 一般情况
if dp[i][j] > max_len: # 更新最长公共子串的长度和终止位置
max_len = dp[i][j]
end_pos = i
else:
dp[i][j] = 0
if max_len == 0: # 没有找到公共子串
return ""
else:
return str1[end_pos-max_len+1:end_pos+1]
本题是一道字符串处理的经典问题,通过使用动态规划的思想,我们可以用 $O(mn)$ 的时间复杂度来解决它。需要注意的是,由于我们需要求出最小公共子串,而最小公共子串的长度可能为 0,因此在进行返回结果的时候需要添加特判。