问题
给定两个字符串str1和str2,输出两个字符串的最长公共子串。
问题分析
利用动态规划,依次匹配str1[i]和str2[j]判断是否相同:
1.相同,上一步匹配的子串长度为dp[i-1][j-1],则状态转换dp[i][j] = dp[i-1][j-1]+1,同时记录新的子串匹配的终点indxend;
2.不相同,则状态dp[i][j]=0(匹配的是连续公共子串,所以当前字符不匹配,长度更新为0)
注意:若匹配的字符串任意一个位于字符串的起始位置,则说明之前不可能存在匹配的子串,所以dp[i][j]=1 (i0 or j0).
字符串 | a | b | c | d | e |
---|---|---|---|---|---|
c | 0 | 0 | 1 | 0 | 0 |
a | 1 | 0 | 0 | 0 | 0 |
b | 0 | 2 | 0 | 0 | 0 |
e | 0 | 0 | 0 | 0 | 1 |
d | 0 | 0 | 0 | 1 | 0 |
如上表,str1=‘abcde’,str2=cabed,最长公共子串为s=ab,maxlen=2。
def findsubstr(s1,s2):
#找出字符串s1和s2之间最长的公共子串
n1 = len(s1)
n2 = len(s2)
dp = [[0]*n2 for _ in range(n1)]
maxlen = 0
idxend = 0
for i in range(n1):
for j in range(n2):
if s1[i]==s2[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]>maxlen: #更新公共子串长度
maxlen = dp[i][j]
idxend = i
return s1[idxend-maxlen+1:idxend+1] #返回公共子串