1. 程式人生 > >編輯距離問題(Edit Distance Problem)

編輯距離問題(Edit Distance Problem)

三種 距離 del 計算 第一個 單個 main iostream namespace

問題描述

設A和B是兩個字符串,要用最少的字符操作將字符串A轉換成字符串B。這裏所說的字符操作包括

1)刪除一個字符;

2)插入一個字符;

3)將一個字符改為另一個字符。

將字符串A變換為字符串B所用的最少字符操作數成為字符串A到B的編輯距離,記為d(A,B)。對任給的2個字符串A和B,計算出它們的編輯距離d(A,B)。

問題分析

這是一道DP問題,DP問題的核心是“全局最優解的部分解是部分子問題的最優解”。構造字符串A,B如下

A:  abcdef

B:  acdefgh

全局最優解B=“abcdef”的部分解B1=“abcde”,是部分子問題A1=“abcde”,B1="acdef"的最優解,抓住此關鍵點,可知應對單個字符進行考慮,進而求出整個字符串的最優解。對第一個字符,B中的’a‘與A中的’a‘相同,因此可以不操作;第二個字符,B中的’c‘與A中的’b‘不同,則此時有三種情況:

1)刪除’c‘

2)插入’b‘

3)將’c‘改為’b‘

計算三種情況下兩個字符串中位置相同且字符相同的字符數量,選擇最大那種方法,然後進行下一個字符的計算。遇到多余的字符,則直接刪去並將編輯距離增加即可。此例中的計算步驟即為“acdefgh”=>"abcdefgh"=>"abcdef"。

#include<iostream>
#include<string>
using namespace std;
int getEqualsNum(string &a, string &b) {
	int num = 0;
	for (unsigned int i = 0; i < a.length()&&i<b.length(); i++) {
		if (a[i] == b[i])num++;
	}
	return num;
}
int max(int a, int b, int c) {
	if (a > b&&a > c)return 1;
	if (b > a&&b > c)return 2;
	return 3;
}
int main() {
	string a, b;
	a = "abcdef";
	b = "acdefg";
	int res = 0;
	for (unsigned int i = 0; i < a.length()&& i < b.length(); i++) {
		if (a[i] == b[i])continue;
		else {
			//獲取三種操作後的字符串與A串相等字符的個數
			int add, del, change;
			string c;
			c = b;
			c.insert(i, a, i);
			add = getEqualsNum(a, c);
			c = b;
			c.erase(i, 1);
			del = getEqualsNum(a, c);
			c = b;
			c[i] = a[i];
			change = getEqualsNum(a, c);

			//選取最優字串,對B串進行處理
			int temp;
			temp = max(add, del, change);
			if (temp == 1)b.insert(i, a, i,1);
			else if (temp == 2)b.erase(i, 1);
			else b[i] = a[i];

			res++;
		}
	}
	int len1 = a.length(), len2 = b.length();
	res += (len1 - len2) >= 0 ? (len1 - len2): -(len1 - len2);
	cout << "A:" << a << endl << "B:" << b << endl;
	cout << "Eidt Distance:" << res << endl;
	system("pause");
	return 0;
}

  

編輯距離問題(Edit Distance Problem)