问题定义:
给定两个字符串s1和s2,两者的编辑距离(edit distance)定义为将s1转换成s2的最小编辑操作(edit operation)次数。通常,编辑操作包括:
- 将一个字符插入字符串
- 从字符串中删除一个字符
- 将字符串中的一个字符替换成另一个字符
基于这些操作的编辑距离有时也称为Levenshtein距离。(注:1965年提出编辑距离概念的俄罗斯科学家的名字)
解决方案:
采用动态规划算法。
定义一个编辑距离矩阵 ed[|s1|+1, |s2|+1],ed[i, j]表示s1的第1个字符到底i个字符和s2的第1个字符到第j个字符的最小编辑距离。
初始化矩阵ed[i, 0] = i; ed[0, j] = j;然后迭代求解即可。
时间复杂度O(|s1|*|s2|)。
上图中矩阵元素[i, j]包含一个2x2的单元,其中右下角的元素是其他3个元素中的最小值,其他3个元素分别是m[i-1, j-1] + 0或1(设取决于s1[i]是否等于s2[j])、m[i-1, j] + 1、m[i, j-1] + 1。
C/C++代码实现如下:
#include <stdio.h>
#include <string>
#include <iostream>
#include <math.h>
using namespace std;
int EditDistance(string s1, string s2);
int main()
{
string s1, s2;
printf("请输入源串和目标串:\n");
cin >> s1 >> s2;
int editDistance = EditDistance(s1, s2);
cout << "源串" << s1 << "和目标串" << s2
<< "的编辑距离为:\n" << editDistance << endl;
return 0;
}
int EditDistance(string s1, string s2)
{
int m = s1.size(),
n = s2.size();
int i, j;
int ed[m+1][n+1]; //编辑距离数组
//初始化数组
for(i=0; i<n+1; i++)
ed[0][i] = i;
for(i=1; i<m+1; i++)
ed[i][0] = i;
//开始求编辑距离
for(i=1; i<m+1; i++) {
for(j=1; j<n+1; j++) {
if(s1[i-1] == s2[j-1])
ed[i][j] = min((ed[i-1][j-1]), min((ed[i-1][j] + 1), (ed[i][j-1] + 1)));
else
ed[i][j] = min((ed[i-1][j-1] + 1), min((ed[i-1][j] + 1), (ed[i][j-1] + 1)));
}
}
return ed[m][n];
}
/******************
Date:2018/7/21
Author:ZNM
******************/