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;
}