一、概念
编辑距离:编辑距离,又称Levenshtein距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。
如:将sailn一字转成failing:
sailn--->failn: (s->f)插入,删除
sailn--->failin: (+i) 插入
sailn--->failing: (+g) 插入
则:sailn与failing的最少编辑距离就是3
问题:找出字符串的编辑距离,即把一个字符串s1最少经过多少步操作变成编程字符串s2,操作有三种,添加一个字符,删除一个字符,修改一个字符
二、思想
函数edit(i, j),它表示第一个字符串的长度为i的子串到第二个字符串的长度为j的子串的编辑距离。
简单描述动态规划公式:
if i == 0 且 j == 0,edit(i, j) = 0
if i == 0 且 j > 0,edit(i, j) = j
if i > 0 且j == 0,edit(i, j) = i
if i ≥ 1 且 j ≥ 1 ,edit(i, j) == min{ edit(i-1, j) + 1, edit(i, j-1) + 1, edit(i-1, j-1) + f(i, j) },当第一个字符串的第i个字符不等于第二个字符串的第j个字符时,f(i, j) = 1;否则,f(i, j) = 0。
计算出两个文本的最少编辑距离之后,如果这个数字越小,那么说明这两篇文章越相似,但是很明显,通过这种方法计算的时间复杂度为,而且需要两两进行计算,所以只适合处理小数据的文本
三、实现
int min(int a, int b)
{
return a < b ? a : b;
}
int edit(string str1, string str2)
{
int max1 = str1.size();
int max2 = str2.size();
int **ptr = new int*[max1 + 1];
for(int i = 0; i < max1 + 1 ;i++)
{
ptr[i] = new int[max2 + 1];
}
for(int i = 0 ;i < max1 + 1 ;i++)
{
ptr[i][0] = i;
}
for(int i = 0 ;i < max2 + 1;i++)
{
ptr[0][i] = i;
}
for(int i = 1 ;i < max1 + 1 ;i++)
{
for(int j = 1 ;j< max2 + 1; j++)
{
int d;
int temp = min(ptr[i-1][j] + 1, ptr[i][j-1] + 1);
if(str1[i-1] == str2[j-1])
{
d = 0 ;
}
else
{
d = 1 ;
}
ptr[i][j] = min(temp, ptr[i-1][j-1] + d);
}
}
cout << "**************************" << endl;
for(int i = 0 ;i < max1 + 1 ;i++)
{
for(int j = 0; j< max2 + 1; j++)
{
cout << ptr[i][j] << " " ;
}
cout << endl;
}
cout << "**************************" << endl;
int dis = ptr[max1][max2];
for(int i = 0; i < max1 + 1; i++)
{
delete[] ptr[i];
ptr[i] = NULL;
}
delete[] ptr;
ptr = NULL;
return dis;
}