前言

動(dòng)態(tài)規(guī)劃

動(dòng)態(tài)規(guī)劃

動(dòng)態(tài)規(guī)劃其實(shí)就是對(duì)

分而治之

策略的一種應(yīng)用, 將一個(gè)較大的問題分解成有限個(gè)的不相關(guān)的子問題問題, 然后通過解決子問題, 不斷推演出最終結(jié)果。

動(dòng)態(tài)規(guī)劃有一個(gè)比較直觀特點(diǎn):

就可以通過表格的方式去描述問題。

動(dòng)態(tài)規(guī)劃應(yīng)用

以下使用動(dòng)態(tài)規(guī)劃進(jìn)行

字符串最短編輯處理

的一個(gè)例子,通過這個(gè)例子就可以很容易的搞懂動(dòng)態(tài)規(guī)劃這個(gè)算法的原理和應(yīng)用。

1、字符的操作方式

字符的三種操作方式: 替換, 刪除, 增加。

舉個(gè)例子:

替換

abc -> abe

里面就需要將c 提換成e, 這里需要的操作次數(shù)是1。

刪除

abc -> ab

里面就需要將c 刪除, 這里需要的操作次數(shù)是1.

增加

a -> ab

里面就需要增加字符b, 這里需要的操作次數(shù)是1.

從上面的例子可以看到, 其實(shí)兩個(gè)字符串即便互相交換, 它們的最短操作距離是一樣的。

2、使用動(dòng)態(tài)規(guī)劃解決最短編輯距離問題

. 將 adceg --> abcfg

步驟一: 初始化表格

. 首先, 我們根據(jù)比較字符串的長度新建一個(gè) (m+1)x(n+1) 的二維表格, 這個(gè)例子中, 這個(gè)表格就是6x6, 當(dāng)然, 需要比較字符串的長度不需要相等.,

. 然后, 初始化首行與首列的數(shù)據(jù)

其實(shí),初始化的原理是和之前說的編輯邏輯保持一致的, 我們先看第一行:

.Null 表示空串, 第0,0 坐標(biāo)的值是0, 表示, "空串" --> "空串" 無需任何編輯操作

.0,1 坐標(biāo)的值是1, 表示從"空串" --> "a", 只需要最少1次編輯操作.

.0,2 坐標(biāo)的值是2, 表示從"空串" --> "ab", 只需要最少2次編輯操作.

同理可得, 第一行剩下的值分別是3,4,5

.同樣地, 我們也可以得到第一列的值分別是 0,1,2,3,4,5

步驟二: 解決字符相等的情況

.完成了初始化后, 我們嘗試填充 1, 1 坐標(biāo)的值

.由于第一行的字母是a, 第一列的字母也是a, 兩者相等,所以我們只需要將(i-1, j-1)也就是(0,0) 的值直接復(fù)制過來, 也就是說, (1,1) 的值是0, 表示無需任何編輯操作.如下圖所示

步驟三: 解決字符不相等的情況:

.好了, 我們繼續(xù)填充(1,2) 坐標(biāo)的值:

.i 對(duì)應(yīng)的值依舊是a, j 對(duì)應(yīng)的值b, 但兩者不相等,這個(gè)時(shí)候, 需要我們就取 replace, insert, remove 操作對(duì)應(yīng)的坐標(biāo)值中的最小值. 這么說可能比較抽象, 我們先從微觀上觀察下每一個(gè)種操作對(duì)應(yīng)的坐標(biāo)值:

假設(shè)當(dāng)前的坐標(biāo)是i,j (i>0, j >0). 那么:

insert 操作對(duì)應(yīng)的坐標(biāo)值是(i, j-1)

replace 操作對(duì)應(yīng)的坐標(biāo)值是 (i-1, j -1)

remove 操作對(duì)應(yīng)的坐標(biāo)值是 (i-1, j)

我們需要做的,就是將這三種操作的最小值找出來, 然后做 +1 操作, 以 (1,2) 為例,填的值就是1:

步驟四: 填充剩余表格

.好了, 到目前為止, 所有的需要分析的步驟就完成了, 剩下就只需要填充后面的值,最后,你會(huì)發(fā)現(xiàn)2 就是最終的求解.

.動(dòng)態(tài)規(guī)劃一個(gè)很大的優(yōu)勢(shì)就是可以通過這個(gè)表格找出任意兩個(gè)子串的最短編輯距離, 比如: abc --> adc 的最短編輯距離就是1

算法實(shí)現(xiàn):

最終的算法實(shí)現(xiàn)(Python)就非常簡單了:

def min_dest(i, j, arr): return min(arr[i-1,j-1], min( arr[i-1,j], arr[i,j-1]))def find_min_edit_distance(str1, str2): arr = [len(str1)][len(str2)] for i in range(len(str1)): for j in range(len(str2)): if i == 0: #初始化第0行 a[i][j] = j continue if j == 0: #初始化第0列 a[i][j] = i continue if str1[i] == str2[j]: #字符相等, 直接復(fù)制 a[i][j] = a[i-1][j-1] else: #字符不等, 去最小值. a[i][j] = min_dest(i, j, arr) return arr[len(str1)-1][len(str2)-1]

總結(jié):

從這個(gè)例子可以看到: 動(dòng)態(tài)規(guī)劃的實(shí)現(xiàn)一點(diǎn)都不難, 難是難在要識(shí)別問題能通過動(dòng)態(tài)規(guī)劃去解決. 我認(rèn)為這個(gè)過程是需要不斷積累經(jīng)驗(yàn)的過程.

1.《動(dòng)態(tài)規(guī)劃 算法篇:一文搞懂 : 動(dòng)態(tài)規(guī)劃之最短編輯距離》援引自互聯(lián)網(wǎng),旨在傳遞更多網(wǎng)絡(luò)信息知識(shí),僅代表作者本人觀點(diǎn),與本網(wǎng)站無關(guān),侵刪請(qǐng)聯(lián)系頁腳下方聯(lián)系方式。

2.《動(dòng)態(tài)規(guī)劃 算法篇:一文搞懂 : 動(dòng)態(tài)規(guī)劃之最短編輯距離》僅供讀者參考,本網(wǎng)站未對(duì)該內(nèi)容進(jìn)行證實(shí),對(duì)其原創(chuàng)性、真實(shí)性、完整性、及時(shí)性不作任何保證。

3.文章轉(zhuǎn)載時(shí)請(qǐng)保留本站內(nèi)容來源地址,http://f99ss.com/keji/347008.html