Levenshtein Distance,又稱Edit Distance,在天然語言處理中有着普遍的應用。Levenshtein Distance 指的是兩個字符串之間,由一個轉換成另外一個所需的最少編輯操做次數。編輯操做包括:1)刪除一個字符;2)插入一個字符;3)替換一個字符html
Example:ios
兩個字符串a = "kitten", b = "ssitting",編輯過程以下:算法
所以,a與b之間的編輯距離等於3。spa
解決方案:動態規劃3d
1)描述最優解結構,尋找最優子結構code
a = {x1, x2..xi}與字符串b = {y1, y2...yj}之間的最小編輯次數leva,b(i, j)。htm
(1) 替換xi ,讓xi 替換yj,編輯距離leva,b(i, j) = leva,b(i-1, j-1) + 1blog
(2) 在a中的第i個位置,插入新字符x讓字符x = yj,leva,b(i, j) = leva,b(i, j-1) + 1遞歸
(3) 在a中的第i個位置, 刪除入字符xi ,leva,b(i, j) = leva,b(i-1, j) + 1字符串
2)遞歸定義最優解
有了上面的分析,遞歸表達式能夠容易的推導出來:
3)自底向上的實現
#include <iostream> using namespace std; /************************************************************************/ /* * a: 源字符串 * b: 目的字符串 * m: 源字符串長度 * n: 目的字符串的長度 /************************************************************************/ int lev_distance(const char* a, const char* b, int m, int n) { int* pre_col = new int[n+1]; int* cur_col = new int[n+1]; for (int i = 0; i != n+1; i++) { pre_col[i] = i; } for (int i = 0; i != m; i++) { cur_col[0] = i + 1; for (int j = 0; j < n; j++) { cur_col[j+1] = min(min(1 + cur_col[j], 1 + pre_col[j+1]), pre_col[j] + (a[i] == b[j] ? 0 : 1)); } swap(pre_col, cur_col); } return pre_col[n]; } int main() { char a[] = "kitten"; char b[] = "sitting"; int dist = lev_distance(a, b, sizeof(a)-1, sizeof(b)-1); cout<<"levenshtein distance:"<<dist<<endl; system("pause"); return 0; }
正常的動態規劃算法須要記錄表格大小是len(a) * len(b),當字符串長度較長的狀況下,將須要很大的存儲空間,上面的算法針對這種狀況作了一個小的改進:lev(i, j)僅依賴於表格中的三個位置,左邊,上方,左上方,所以只要保留當前列與左邊一列就能夠求出lev(i, j)的值了。