1. 程式人生 > >編輯距離演算法——動態規劃

編輯距離演算法——動態規劃

概念解釋:
編輯距離,又稱Levenshtein距離,是指兩個字串之間,由一個轉成另一個所需的最少編輯操作次數,如果它們的距離越大,說明它們越是不同,所以一般會用來表示兩個字串的相似度。允許的操作包括修改一個字元,插入一個字元,刪除一個字元。應用範圍非常廣泛,例如抄襲檢測,NLP。
要想知道從一個字串轉成另一個字串的最少變換次數,我們就需要用一個演算法,來求出兩個字串之間的最小編輯距離,最經典的演算法,就是動態規劃。

演算法思路:
動態規劃演算法,如果一直死摳細節是永遠找不到狀態和轉移方程的,還是要更加註重狀態的轉移。在這個問題裡面,字串變換的方法有修改、刪除、插入三種,那麼我們的轉移方程應該也包含三個部分,首先是狀態

,定義如下:
兩個字串A,B,長度分別為n,m,狀態dp[i][j]表示A字串0 ~ i 子串與B字串0 ~ j 子串之間的編輯距離,那麼可以得到狀態轉移方程
**插入:**dp[i][j] = dp[i][j-1] + 1
**刪除:**dp[i][j] = dp[i-1][j] + 1
**修改:**dp[i][j] = dp[i-1][j-1] + !(A[i]==B[j])
三者的最小值,就是狀態dp[i][j]的解
之後是初始狀態,很明顯,dp[0][0]=0,dp[i][0]=i,dp[0][j]=j 。

程式碼:

#include <cstdio>
#include <cstring>
#include <iostream> #include <algorithm> using namespace std; int len1, len2, dp[1005][1005]; char st1[1005], st2[1005]; int main() { while(~scanf("%d %s %d %s",&len1,st1,&len2,st2)) { memset(dp,0,sizeof(dp)); for(int i=0;i<=len1;i++) dp[i][0]=i; for
(int j=0;j<=len2;j++) dp[0][j]=j; for(int i=1;i<=len1;i++) { for(int j=1;j<=len2;j++) { dp[i][j]=min(min(dp[i-1][j]+1,dp[i][j-1]+1), dp[i-1][j-1]+(st1[i-1]!=st2[j-1])); } } printf("%d\n",dp[len1][len2]); } return 0; }

總結:
雖然思路挺簡單,程式碼也不長,編輯距離的概念也是在實際中應用廣泛的一個東西,也讓我再次體會到動規的神奇。