動態規劃法(十一)編輯距離

2022-07-01 18:33:10 字數 3375 閱讀 3564

試問最小需要多少次這樣的操作才能使得s1轉換為s2?

比如,單詞「cat」和「hat」,這樣的操作最少需要一次,只需要把「cat」中的「c」替換為「h」即可。單詞「recall」和「call」,這樣的操作最少需要兩次,只需要把「recall」中的「r」和「e」去掉即可。單詞「sunday」和「saturday」,這樣的操作最少需要3次,在「sunday」的「s」和「u」中插入「a」和「t」,再把「n」替換成「r」即可。

那麼,是否存在一種高效的演算法,能夠快速、準確地計算出兩個字串的編輯距離呢?

我們使用動態規劃演算法(dynamic programming)來計算出兩個字串的編輯距離。

我們從兩個字串s1和s2的最末端向前遍歷來考慮。假設s1的長度為m,s2的長度為n,演算法如下:

如果兩個字串的最後乙個字元一樣,那麼,我們就可以遞迴地計算長度為m-1和n-1的兩個字串的情形;

如果兩個字串的最後乙個字元不一樣,那麼,進入以下三種情形:

這樣,我們就有了子結構問題。對於動態規劃演算法,我們還需要乙個初始化的過程,然後中間維護一張二維表即可。初始化的過程如下: 如果m為0,則至少需要操作n次,即在s1中逐個新增s2的字元,一共是n次;如果n為0,則至少需要操作m次,即把s1的字元逐個刪除即可,一共是m次。

# -*- coding: utf-8 -*-

# using dynamic programming to solve edit distance problem

# s1, s2 are two strings

def editdistdp(s1, s2):

m, n = len(s1), len(s2)

# create a table to store results of subproblems

dp = [[0 for _ in range(n+1)] for _ in range(m+1)]

# using dp in bottom-up manner

for i in range(m + 1):

for j in range(n + 1):

# if first string is empty, only option is to

# isnert all characters of second string, thus the

# min opration is j

if i == 0:

dp[i][j] = j

# if second string is empty, only option is to

# remove all characters of second string, thus the

# min opration is i

elif j == 0:

dp[i][j] = i

# if last characters are same, ignore last character

# and recursive for remaining string

elif s1[i-1] == s2[j-1]:

dp[i][j] = dp[i-1][j-1]

# if last character are different, consider all

# possibilities and find minimum of inserting, removing, replacing

else:

dp[i][j] = 1 + min(dp[i][j-1], # insert

dp[i-1][j], # remove

dp[i-1][j-1]) # replace

return dp[m][n]

# driver program

s1 = "sunday"

s2 = "saturday"

edit_distance = editdistdp(s1, s2)

print("the edit distance of '%s' and '%s' is %d."%(s1, s2, edit_distance))

輸出結果如下:

the edit distance of 'sunday' and 'saturday' is 3.
package dp_example;

// 計算兩個字串的編輯距離(edit distance)

public class edit_distance

/*函式edit_distanc: 計算兩個字串的編輯距離(edit distance)

傳入引數: 兩個字串str1和str2

返回: 編輯距離

*/public static int edit_distance(string str1, string str2)

/* if second string is empty, only option is to

* remove all characters of second string, thus the

* min opration is i

*/else if(j == 0)

/* if last characters are same, ignore last character

* and recursive for remaining string

*/else if(str1.charat(i-1) == str2.charat(j-1))

/*if last character are different, consider all

*possibilities and find minimum of inserting, removing, replacing

*/else}}

return dp[m][n];

}public static int min(int i, int j)

}

輸出結果如下:

the edit distance of 'cat' and 'hat' is 1.
# 利用nltk中的edit_distance計算兩個字串的edit distance

from nltk.metrics import edit_distance

s1 = "recall"

s2 = "call"

t = edit_distance(s1, s2)

print("the edit distance of '%s' and '%s' is %d." % (s1, s2, t))

輸出結果如下:

the edit distance of 'recall' and 'call' is 2.

動態規劃法

在學習動態規劃法之前,我們先來了解動態規劃的幾個概念 1 階段 把問題分成幾個相互聯絡的有順序的幾個環節,這些環節即稱為階段。2 狀態 某一階段的出發位置稱為狀態。3 決策 從某階段的乙個狀態演變到下乙個階段某狀態的選擇。4 狀態轉移方程 前一階段的終點就是後一階段的起點,前一階段的決策選擇匯出了後...

動態規劃法

有些問題在分解時會產生許多子問題,且分解出的自問題互相交織,因而在解這類問題時,將可能重複多次解乙個子問題。這種重複當然是不必要的,解決方法可以在解決每個子問題後把它的解 包括其子子問題的解 保留在乙個 中,若遇到求與之相同的子問題時,dp演算法又稱動態規劃,是資訊學競賽中選手必須熟練掌握的一種演算...

動態規劃法

最近遇到了一道挺有意思的演算法題 四種硬幣 1元3元4元5元 問 想要湊成n元錢最少幾枚硬幣?public class coinsgamemain fun 7,is public static void fun int k,int is i1 l min i2 if l k private stat...