这道题属于动态规划中十分经典的题目,在两个字符串中找到最长的公共子串,返回其最大长度或最大字符串。
一、解题思路
我们可以让两个字符串分别作为一个二维矩阵的行和列,然后比较二维矩阵中每个点对应的行列字符串中的字符是否相同,如果相同设置为1,否则设置为0。接着只需要查找值为1的最长对角线就可以解决。
对于以下两个字符串为例:
str1="asdfas"
str2="werasdfaswer"
可以发现,我们所找寻的公共子串就是图中的几条对角线,而长的公共子串就是对角线最长的那一个。
二、动态规划
动态规划的核心就是如何转移,如何利用上一步的结果,根据当前的条件判断,得出现在状态的结果:
record[i][j]=1可以演变为record[i][j]=1+record[i-1][j-1]
三、函数实现输出最长公共子串长度
def lcs_max_num(str1, str2):
m = len(str1)
n = len(str2)
max_num = 0
# 构造一个(m+1)*(n+1)的二维数组来存储LCS的长度
lcs_len = [[0] * (n + 1) for i in range(m + 1)]
# 动态规划求解LCS的长度
for i in range(1, m + 1):
for j in range(1, n + 1):
if str1[i - 1] == str2[j - 1]:
lcs_len[i][j] = lcs_len[i - 1][j - 1] + 1
if max_num < lcs_len[i][j]:
max_num = lcs_len[i][j]
return max_num
if __name__ == "__main__":
str1 = 'asdfas'
str2 = 'werasdfaswer'
print(lcs_max_num(str1, str2))
四、函数实现输出最长公共子串
def lcs_max_char(str1, str2):
m = len(str1)
n = len(str2)
# 构造一个(m+1)*(n+1)的二维数组来存储LCS的长度
lcs_len = [[0] * (n + 1) for i in range(m + 1)]
# 动态规划求解LCS的长度
for i in range(1, m + 1):
for j in range(1, n + 1):
if str1[i - 1] == str2[j - 1]:
lcs_len[i][j] = lcs_len[i - 1][j - 1] + 1
else:
lcs_len[i][j] = max(lcs_len[i - 1][j], lcs_len[i][j - 1])
# 根据LCS的长度求解LCS的文本
lcs_text = ""
i = m
j = n
while i > 0 and j > 0:
if str1[i - 1] == str2[j - 1]:
lcs_text = str1[i - 1] + lcs_text
i -= 1
j -= 1
elif lcs_len[i - 1][j] > lcs_len[i][j - 1]:
i -= 1
else:
j -= 1
return lcs_text
if __name__ == "__main__":
str1 = 'asdfas'
str2 = 'werasdfaswer'
print(lcs_max_char(str1, str2))