题目来源:牛客网第127题
给定两个字符串str1和str2,输出两个字符串的最长公共子串
题目保证str1和str2的最长公共子串存在且唯一。
输入:“1AB2345CD”,“12345EF”
返回值:“2345”
简单思路
最简单的想法是从第一个开始遍历,用i表示第一个字符串的索引, j 表示第二个字符串的索引,遍历到两个串中的相同字母时,使用count计数,找到该位置起最长的连续同样字母的计数,即 i + count, j + count.
这样做可以解出来,但是耗时较长,因为每次遇见相同的字母都需要从1开始遍历,无法利用之前走过的步骤的解
动态规划解:
使用dp[i][j]
表示在str1中的第i个字符,对应str2中的第j个字符
如果不相等,dp[i][j] = 0
, 如果相等,等于两个字符串的前一个索引的值 +1
可以得到下面的递推公式:
dp[i][j] = dp[i-1][j-1] + 1
遇到的问题:
-
发现牛客网不支持numpy,只能使用原生库生成list二维数组
-
在使用list过程中,刚开始定义的二维数组是使用 list_two = [[0] * 3] * 3, 实际运行过程中,发现使用 dps[i+1][j+1]赋值操作无效,查询知乎解答后发现是浅拷贝问题,改为
list_three = [[0 for i in range(3)] for j in range(3)]
后可以啦
完整代码:
```
class Solution:
def LCS(self , str1: str, str2: str) -> str:
# write code here
l1 = len(str1) + 1
l2 = len(str2) + 1
# count the number of str
count = 0
# save the result str
position = 0
# 深拷贝和浅拷贝
dps = [[0 for i in range(l2)] for j in range(l1)]
for i in range(0, l1-1):
for j in range(0, l2-1):
if str1[i] == str2[j]:
print(dps)
dps[i+1][j+1] = dps[i][j] + 1
print(dps[i][j], count, dps[i+1][j+1])
if count < dps[i+1][j+1]:
count = dps[i+1][j+1]
position = i
else:
dps[i+1][j+1] = 0
return str1[position - count + 1 : position + 1]
```
后续优化:
可以将二维数组改为一维数组, 节省空间
算法复杂度和动态规划对比分析,后续博客陆续补充