[演算法筆記]動態規劃之最長公共子串和最長公共子序列

vimiix發表於2018-02-07

本文是《演算法圖解》筆記

應用場景

一切脫離實際應用場景的演算法都是耍流氓!

  • 生物學家根據最長公共序列來確定 DNA 鏈的相似性,進而判斷兩種動物或疾病有多相似。最長公共序列還被用來尋找多發性硬化症治療方案。
  • 原始碼管理中,git diff指令,可以查詢出編輯前後檔案的差異,這是基於動態規劃實現的。
  • 編輯距離(levenshtein distance),判斷字串的相似程度,也是基於動態規劃計算。可以通過這個技術從拼寫檢查到判斷使用者上傳的資料是否是盜版。(這樣看來,我猜想大學論文查重應該也是基於動態規劃演算法:P
  • Microsoft Word等軟體中具有斷字功能,使用動態規劃可以確定什麼地方斷字以確保行長一致。

最長公共子串

場景:

某個使用者在網站搜尋框中輸入一個字串 hish,但其實使用者想輸入的是 fish

介紹這個網站的可選字典裡面只有 fishvista 這兩個相似單詞

猜測使用者到底想要搜尋的是什麼字串?

在動態規劃中,目標是要將某個指標最大化,在這個例子中,要找出兩個單詞的公共子串。更大的那個即為結果。

求解網格:
注:只列出hish的例子,vista思路相同
h i s h
f 0 0 0 0
i 0 1 0 0
s 0 0 2 0
h 1 0 0 3
演算法描述:
  1. 如果兩個字母不同,值為0
  2. 如果兩個字母相同,值為左上角鄰居的值加一
虛擬碼:
if word_a[i] == word_b[j]:
	cell[i][j] = cell[i-1][j-1] + 1
else:
	cell[i][j] = 0
複製程式碼

最長公共子序列

場景

假設使用者不小心輸入了 fosh ,要判斷他原本要輸入的是 fish 還是 fort

這時候需要使用最長公共子序列來比較

求解網路:
f o s h
f 1 1 1 1
i 1 1 1 1
s 1 1 2 2
h 1 1 2 3
演算法描述:
  1. 如果兩個字母不同,就選擇上方和左方鄰居格子中較大的那個值
  2. 如果兩個字母相同,值為左上方格子中的值加一
虛擬碼:
if word_a[i] == word_b[j]:
	cell[i][j] = cell[i-1][j-1] + 1
else:
	cell[i][j] = max(cell[i-1][j], cell[i][j-1])
複製程式碼

部落格地址: vimiix.com

相關文章