编辑距离,又称Levenshtein距离(也叫做Edit Distance),是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。
例如将kitten一字转成sitting:
sitten (k->s)
sittin (e->i)
sitting (->g)
所以kitten和sitting的编辑距离是3。俄罗斯科学家Vladimir Levenshtein在1965年提出这个概念。
给出两个字符串a,b,求a和b的编辑距离。
Input
第1行:字符串a(a的长度 <= 1000)。 第2行:字符串b(b的长度 <= 1000)。
Output
输出a和b的编辑距离
Input示例
kitten sitting
Output示例
3
李陶冶
(题目提供者)
C++的运行时限为:1000 ms ,空间限制为:131072 KB
示例及语言说明请按这里
ans[i][j]表示字符串s1(0~i)与字符串s2(0~j)的编辑距离
ans[i][j]是由三个方向推知:1.(上)a[i-1][j]+1, 2.(左)a[i][j-1]+1, 3.(左上)if(s1[i]=s2[j]) a[i-1]a[j-1] else a[i-1][j-1]+1.
在这三个方向选一个最小的
为什么有这个
ans[i][j] = min(ans[i][j] , min(ans[i-1][j] + 1 , ans[i][j-1] + 1))
状态方程
看表:
数字是什么意思?
s | i | t | t | i | n | g | ||
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
k | 1 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
i | 2 | 2 | 1 | 2 | 3 | 4 | 5 | 6 |
t | 3 | 3 | 3 | 1 | 2 | 3 | 4 | 5 |
t | 4 | 4 | 4 | 2 | 1 | 2 | 3 | 4 |
e | 5 | 5 | 5 | 3 | 2 | 2 | 3 | 4 |
n | 6 | 6 | 6 | 4 | 3 | 3 | 2 | 3 |
第二行:1对应s,可以看成空字符串变为“s”需要改变1次,2对应i可以看成空字符串变为“si"需要改变2次。
第三行:第一个1对应空格即空字符,需要改变1次(删除k),第二个1对应s,需要改变一次(k->s),
2对应i,需要改变2次(k->si).
第三行:
第一个2对应空格即空字符,需要改变2次(删除)(ki->空),第二个2对应s,需要改变2次(ki->s)
1对应i,需要改变1次(ki-si),也就是如果s1[i]==s2[j],就不需再多加改变.
任何一个ans[i][j]都是和以上一样的模拟,以上是横着看但竖着看也是一样的。只要在三个方向的状态选一个最小的,就表示当前最小编辑距离。
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define LL long long
#define MAX 1020
char s1[MAX];
char s2[MAX];
int ans[MAX][MAX]; //结果矩阵
int main()
{
scanf ("%s%s",s1+1,s2+1);
int l1,l2;
s1[0] = s2[0] = '@';
l1 = strlen(s1) - 1;
l2 = strlen(s2) - 1;
for (int i = 0 ; i <= max(l1,l2) ; i++) //初始化矩阵
ans[0][i] = ans[i][0] = i;
for (int i = 1 ; i <= l1 ; i++)
{
for (int j = 1 ; j <= l2 ; j++)
{
//下面三者取最小值
if (s1[i] != s2[j]) //如果这个点对应两字符相等,那么取左上方数字,否则取左上方数字加一
ans[i][j] = ans[i-1][j-1] + 1;
else
ans[i][j] = ans[i-1][j-1];
ans[i][j] = min(ans[i][j] , min(ans[i-1][j] + 1 , ans[i][j-1] + 1)); //然后再与左方数字+1、上方数字+1取最小值
}
}
printf ("%d\n",ans[l1][l2]); //右下角的数字即为结果(编辑距离)
return 0;
}