算法 【第九章】動態規劃問題

動態規劃算法是經過拆分問題,定義問題狀態和狀態之間的關係,使得問題可以以遞推的方式去解決。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次)

  • x="coffee" y="coffe",編輯距離爲(刪除1次)
  • x="coffee" y="coffye",編輯距離爲(替換2次)
  • x="cofye" y="coffee",編輯距離爲2

編輯距離能夠用來表示兩個字符串的類似度,應用普遍
動態規劃最優子結構:

斜着過來是替換

從左邊來的是插入

從上面來的是刪除

。。。。。。。。。。

相關文章
相關標籤/搜索