1. 程式人生 > >C++實現兩個字串之間的Levenshtein Distance(編輯距離)

C++實現兩個字串之間的Levenshtein Distance(編輯距離)

1.什麼是Levenshtein Distance

Levenshtein Distance,又稱編輯距離,指的是兩個字串之間,由一個轉換成另一個所需的最少編輯操作次數。許可的編輯操作包括將一個字元替換成另一個字元,插入一個字元,刪除一個字元。levenshtein() 函式返回兩個字串之間的 Levenshtein 距離。編輯距離的演算法是首先由俄國科學家Levenshtein提出的,故又叫Levenshtein Distance。

2.演算法

步驟 說明
1 設定n為字串s的長度。("GUMBO") 
設定m為字串t的長度。("GAMBOL") 
如果n等於0,返回m並退出。
如果m等於0,返回n並退出。
構造兩個向量v0[m+1] 和v1[m+1],串聯0..m之間所有的元素。
2 初始化 v0 to 0..m。
3 檢查 s (i from 1 to n) 中的每個字元。
4 檢查 t (j from 1 to m) 中的每個字元
5 如果 s[i] 等於 t[j],則編輯代價為 0;
如果 s[i] 不等於 t[j],則編輯代價為1。
6 設定單元v1[j]為下面的最小值之一:
a、緊鄰該單元上方+1:v1[j-1] + 1
b、緊鄰該單元左側+1:v0[j] + 1
c、該單元對角線上方和左側+cost:v0[j-1] + cost
7 在完成迭代 (3, 4, 5, 6) 之後,v1[m]便是編輯距離的值。

其中,cost為編輯代價,當字元相等時,為0,否則為1.

下面將演示如何計算"GUMBO"和"GAMBOL"兩個字串的Levenshtein距離

步驟1、2

v0 v1
G U M B O
0 1 2 3 4 5
G 1
A 2
M 3
B 4
O 5
L 6

步驟3-6,當 i = 1

v0 v1
G U M B O
0 1 2 3 4 5
G 1 0
A 2 1
M 3 2
B 4 3
O 5 4
L 6
5

步驟3-6,當 i = 2

v0 v1
G U M B O
0 1 2 3 4 5
G 1 0 1
A 2 1 1
M 3 2 2
B 4 3 3
O 5 4 4
L 6 5 5

步驟3-6,當 i = 3

v0 v1
G U M B O
0 1 2 3 4 5
G 1 0 1 2
A 2 1 1 2
M 3 2 2 1
B 4 3 3 2
O 5 4 4 3
L 6 5 5 4

步驟3-6,當 i = 4

v0 v1
G U M B O
0 1 2 3 4 5
G 1 0 1 2 3
A 2 1 1 2 3
M 3 2 2 1 2
B 4 3 3 2 1
O 5 4 4 3 2
L 6 5 5 4 3

步驟3-6,當 i = 5

v0 v1
G U M B O
0 1 2 3 4 5
G 1 0 1 2 3 4
A 2 1 1 2 3 4
M 3 2 2 1 2 3
B 4 3 3 2 1 2
O 5 4 4 3 2 1
L 6 5 5 4 3 2

步驟7

編輯距離就是矩陣右下角的值,v1[m] == 2。

3.程式碼實現

#include <iostream>
#include <vector>
#include <string>
#include <cmath>
using namespace std;

#define  min(a,b) ((a<b)?a:b)

//演算法
int ldistance(const string source, const string target)
{
	//step 1

	int n = source.length();
	int m = target.length();
	if (m == 0) return n;
	if (n == 0) return m;
	//Construct a matrix
	typedef vector< vector<int> >  Tmatrix;
	Tmatrix matrix(n + 1);
	for (int i = 0; i <= n; i++)  matrix[i].resize(m + 1);

	//step 2 Initialize

	for (int i = 1; i <= n; i++) matrix[i][0] = i;
	for (int i = 1; i <= m; i++) matrix[0][i] = i;

	//step 3
	for (int i = 1; i <= n; i++)
	{
		const char si = source[i - 1];
		//step 4
		for (int j = 1; j <= m; j++)
		{

			const char dj = target[j - 1];
			//step 5
			int cost;
			if (si == dj){
				cost = 0;
			}
			else{
				cost = 1;
			}
			//step 6
			const int above = matrix[i - 1][j] + 1;
			const int left = matrix[i][j - 1] + 1;
			const int diag = matrix[i - 1][j - 1] + cost;
			matrix[i][j] = min(above, min(left, diag));

		}
	}//step7
	return matrix[n][m];
}
void main(){
	string s;
	s = "ABC";
	string d;
	d = "abcd";
	//cout << "source=";
	//cin >> s;
	//cout << "diag=";
	//cin >> d;
	int dist = ldistance(s, d);
	cout << "dist=" << dist << endl;
	system("pause");
}

參考資源: