動態規劃算法是經過拆分問題,定義問題狀態和狀態之間的關係,使得問題可以以遞推的方式去解決。css
動態規劃的核心點:定義狀態與轉移方程(最優子結構)
從新定義問題:算法
1、最長上升子序列(LIS):給定一個序列X,求X長度最大的連續遞增的子序列。
例:X=[1,7,2,8,3,5,2],LIS(X)=[1,2,3,5]app
def LIS(x): F = [0 for _ in range(len(x))] p = [-1 for _ in range(len(x))] # 初始化 F[0] = 1 p[0] = -1 for k in range(1, len(F)): max_loc = -1 max_num = 0 # 內層循環表示F[0:k]裏全部小於x[k]的對應位置的F[i]的最大值 for i in range(0, k): if x[i] < x[k]: if F[i] > max_num: max_loc = i max_num = F[i] F[k] = max_num + 1 p[k] = max_loc max_i = 0 for i in range(1,len(F)): if F[i] > F[max_i]: max_i = i lis = [] i = max_i while i >= 0: lis.append(x[i]) i = p[i] lis.reverse() return lis # print(LIS([9,7,2,8,3,5,2]))
2、最長公共子序列(LCS)問題:給定兩個序列X和Y,求X和Y長度最大的公共子序列。3d
例:X="ABBCBDE" Y="DBBCDB" LCS(X,Y)="BBCD"code
動態規劃最優子結構:blog
def LCS(x, y): F = [[0 for _ in range(len(y)+1)] for _ in range(len(x)+1)] p = [[0 for _ in range(len(y)+1)] for _ in range(len(x)+1)] for i in range(1, len(x)+1): p[i][0] = 2 for j in range(1, len(y)+1): p[0][j] = 1 # 0 斜向 1 橫向 j-1 2豎向 i-1 for i in range(1, len(x)+1): for j in range(1, len(y)+1): if x[i-1] == y[j-1]: F[i][j] = F[i-1][j-1]+1 p[i][j] = 0 else: #F[i][j] = max(F[i-1][j], F[i][j-1]) if F[i-1][j] > F[i][j-1]: F[i][j] = F[i-1][j] p[i][j] = 2 else: F[i][j] = F[i][j-1] p[i][j] = 1 lcs = [] i = len(x) j = len(y) while i > 0 or j > 0: if p[i][j] == 0: lcs.append(x[i-1]) i -= 1 j -= 1 elif p[i][j] == 1: j -= 1 else: i -= 1 lcs.reverse() return lcs #return F[i][j] # print(LCS("ABBCBDE", "DBBCDB"))
3、最長公共子序列(LCSS)問題:給定兩個序列X和Y,求X和Y長度最大的公共子串。字符串
例:X="ABBCBDE" Y="DBBCDB" LCSS(X,Y)="BBC"class
暴力搜索求解:O(n3)搜索
動態規劃最優子結構:循環
def LCSS(x, y): F = [[0 for _ in range(len(y)+1)] for _ in range(len(x)+1)] p = [[0 for _ in range(len(y)+1)] for _ in range(len(x)+1)] # 0 不匹配 1匹配 for i in range(1, len(x)+1): for j in range(1, len(y)+1): if x[i-1] == y[j-1]: F[i][j] = F[i-1][j-1]+1 p[i][j] = 1 else: F[i][j] = 0 p[i][j] = 0 max_val = 0 max_i = 0 max_j = 0 for i in range(1, len(x)+1): for j in range(1, len(y)+1): if F[i][j] > max_val: max_val = F[i][j] max_i = i max_j = j #tracback lcss = [] i = max_i j = max_j while p[i][j] == 1: lcss.append(x[i-1]) i -= 1 j -= 1 lcss.reverse() return lcss print(LCSS("ABBCBDE", "DBBCDB"))
4、編輯距離:指兩個字串之間,由一個轉成另外一個所需的最少編輯操做次數。
容許的編輯操做:替換、插入、刪除x="cofe" y="coffee",編輯距離爲2(插入2次)
編輯距離能夠用來表示兩個字符串的類似度,應用普遍
動態規劃最優子結構:
斜着過來是替換
從左邊來的是插入
從上面來的是刪除
。。。。。。。。。。