1. 程式人生 > >dp基礎之劃分型劃分最小劃分次數

dp基礎之劃分型劃分最小劃分次數

問題:給定一個字串S[0,..n-1],最少劃分幾次使得每個子串都是迴文串

確定狀態:最優策略中最後一段迴文串是S[j...n-1]
    需要知道S前j個字元[0...j-1]最少可以劃分成幾個迴文串
子問題:
設:S前i個字元[0...i-1]最少可以劃分成f[i]個迴文串
    f[i] = min{f[j]+`1 | S[j...i-1]是迴文串}
              {S前j個字元可以最少劃分成幾個迴文串+最後一段迴文串}
初始條件:
f[0] = 0,前0個即空串是0
計算順序:f[0]...f[n]

判斷迴文串:

分為奇數長度迴文串和偶數長度迴文串。
對每個字元進行列舉,兩邊擴充套件,建立一個二維陣列,huiwen[i][j]表示字串S[i...j]是否是迴文串,1表示是,0表示不是

 

程式碼及註釋如下:

import sys
def min_huiwen(S):
    n = len(S)
    if n == 0:
        return 0
    #建立一個二維陣列huiwen[i][j]表示字串S[i...j]是否是迴文串,初始為0,即都不是迴文串
    huiwen = [[0 for i in range(n)] for j in range(n)]
    #賦值huiwen[][j]
    for t in range(n):
        #對於奇數長度迴文串,從t向兩頭拓展
        i = t
        j = t
        while i>=0 and j<n and S[i] == S[j]:
            huiwen[i][j] = 1
            i -= 1
            j += 1
        #對於偶數長度迴文串
        i = t
        j = t+1
        while i>=0 and j<n and S[i] == S[j]:
            huiwen[i][j] = 1
            i -= 1
            j += 1
    #S前i個字元[0...i-1]最少可以劃分成f[i]個迴文串       
    f = [sys.maxsize for i in range(n+1)]
    f[0] = 0
    for j in range(1,n+1):
        #f[i] = min{f[j]+`1 | S[j...i-1]是迴文串}
        for i in range(j):
            if huiwen[i][j-1] == 1:
                f[j] = min(f[i]+1,f[j])
    #劃分次數是個數-1
    return f[n]-1
S = ['a','a','b']
print(min_huiwen(S))
#結果:1