【演算法 in python | DP】LCS最長公共子串
阿新 • • 發佈:2018-11-07
1. LCS,最長公共子串
動態規劃,狀態轉移方程:
#該版本是返回最長公共子串和其長度,若只返回長度,則可以簡化 def lcs(s1, s2): l1 = len(s1) l2 = len(s2) # res[i][j]儲存子串s1[0:i] 和 子串s2[0:j] 的lcs串 # num[i][j]儲存子串s1[0:i] 和 子串s2[0:j] 的lcs長度 #由於考慮到空串也作為比較元素,則將兩個字串的長度各加一 res = [['' for i in range(l2+1)] for j in range(l1+1)] num = [[0 for i in range(l2+1)] for j in range(l1+1)] for i in range(1,l1+1): for j in range(1, l2+1): if s1[i-1] == s2[j-1]: num[i][j] = num[i-1][j-1]+1 res[i][j] = res[i-1][j-1] + s1[i-1] else: if num[i-1][j] > num[i][j-1]: num[i][j] = num[i-1][j] res[i][j] = res[i-1][j] else: num[i][j] = num[i][j-1] res[i][j] = res[i][j-1] return num[-1][-1],res[-1][-1]
簡化版本:只返回最長LCS的長度。
def lcs(s1, s2): l1 = len(s1) l2 = len(s2) # num[i][j]儲存子串s1[0:i] 和 子串s2[0:j] 的lcs長度 #由於考慮到空串也作為比較元素,則將兩個字串的長度各加一 num = [[0 for i in range(l2+1)] for j in range(l1+1)] for i in range(1,l1+1): for j in range(1, l2+1): if s1[i-1] == s2[j-1]: num[i][j] = num[i-1][j-1]+1 else: num[i][j] = max(num[i-1][j], num[i][j-1]) return num[-1][-1]
2. 平方串
如果一個字串S是由兩個字串T連線而成,即S = T + T, 我們就稱S叫做平方串,例如"","aabaab","xxxx"都是平方串.
牛牛現在有一個字串s,請你幫助牛牛從s中移除儘量少的字元,讓剩下的字串是一個平方串。換句話說,就是找出s的最長子序列並且這個子序列構成一個平方串。
即將s分成兩個子串,找出兩個子串的lcs,然後取最大的lcs的二倍。
def squreStr(s): #將s分成兩個子串,找出對應的lcs,在所有的lcs中找出最大的,其二倍即為對應的平方串的長度 res = 0 for i in range(1,len(s)): s1 = s[0:i] s2 = s[i:] res = max(res,lcs(s1,s2)) return res*2