編輯距離演算法——動態規劃
阿新 • • 發佈:2019-01-24
概念解釋:
編輯距離,又稱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;
}
總結:
雖然思路挺簡單,程式碼也不長,編輯距離的概念也是在實際中應用廣泛的一個東西,也讓我再次體會到動規的神奇。