首先是用dp来解这道题,dp解的话关键就在于找到状态转移方程,这个题的状态转移方程和找最长公共子序列不同,因为子串必须要是连续的串。 LCS[i][j]为以s1[i]和s2[j]为结尾最长子串,因此就容易得到状态转移方程了,if s1[i]!=s2[j]的话,那么LCS[i][j]='',而如果s1[i]==s2[j]的话,那么LCS[i][j]=LCS[i-1][j-1]+s1[i]。有了状态转移方程之后就很好写代码了,但是用python写dp的话会报时间复杂度不过关,应该是python语言导致的,复杂度肯定是满足要求的。
但是从状态转移方程就可以看出来这道题用dp做确实有点浪费,可以用划窗来做,new两个指针p1和p2,两个指针中间就构成了一个划窗,然后不断移动划窗找到最大子串。当s1[p1:p2]在s2中,p2右移一个,不在的话p1右移一个,不过要注意p1不可以超过p2,因此p1=p2了之后,就p2右移即可。
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# longest common subsequence
# @param s1 string字符串 the string
# @param s2 string字符串 the string
# @return string字符串
#
class Solution:
def LCS1(self , s1: str, s2: str) -> str:
# dp解题时间复杂度超标,应该是用python写导致的
LCS = [['']*len(s2) for i in range(len(s1))]
maxlcs = ''
# 初始化边界条件,第0行和第0列
for j in range(len(s2)):
if s1[0] == s2[j]:
LCS[0][j]=s1[0]
if len(LCS[0][j]) > len(maxlcs):
maxlcs = LCS[0][j]
else:
pass
for i in range(len(s1)):
if s1[i]==s2[0]:
LCS[i][0] = s2[0]
if len(LCS[i][0]) > len(maxlcs):
maxlcs = LCS[i][0]
else:
pass
# print(LCS)
for i in range(1,len(s1)):
for j in range(1,len(s2)):
if s1[i] == s2[j]:
LCS[i][j] = LCS[i-1][j-1] + s1[i]
if len(LCS[i][j]) > len(maxlcs):
maxlcs = LCS[i][j]
else:
pass
return maxlcs
def LCS(self,s1,s2):
# 划窗法
res = '' # 保存最长子串
p1 = 0 ; p2 = 0
while p2<=len(s1):
if s1[p1:p2] in s2:
if len(s1[p1:p2]) > len(res):
res = s1[p1:p2]
p2+=1
else:
if p1<p2:
p1+=1
else:
p2+=1
return res
s1 = '1A23'
s2 = '123'
print(Solution().LCS(s1,s2))