// ACW902 最短编辑距离
/*
解题思路: DP O(n2)
状态表示 :f(i,j)表示: 把字符串 a的前i个字母 变成 字符串b的前j个字母 所需的 最少操作次数。
状态转移:f(i,j) = min { (f(i,j-1)+1), (f(i-1,j)+1), f(i-1,j-1)+1 }
即最后一步,我们执行的一定是 增 删 改 其中一种操作,取 三种转移方式 的 最小值 即可,其中修改转生的
转移状态不一定要 +1,因为a[i]和b[j]可能正好想等,这里以要判断一下。
推导顺序:
我们可以把推导的过程 当成 填表格的过程,填第 i 行,第 j 列 的数字时,需要用到左方,
上方,左上方区域的数字,所以我们一行一行从左到右,从上到下推导即可。
边界值: 0 行 、0列 的值不能通过状态转移方程推导,且不为0,所以需要单独赋值。
*/
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int lena, lenb, f[N][N];
char a[N], b[N];
int main() {
scanf("%d%s",&lena,a+1);//为了方便推导字符串从数组下标1开始存储
scanf("%d%s",&lenb,b+1);
for(int i=1; i<=lena; i++) f[i][0] = i;
for(int i=1; i<=lenb; i++) f[0][i] = i;
for(int i=1; i<=lena; i++) {
for(int j=1; j<=lenb; j++) {
f[i][j] = min(f[i-1][j]+1,f[i][j-1]+1);
if(a[i]==b[j]) f[i][j] = min(f[i][j],f[i-1][j-1]);
else f[i][j] = min(f[i][j],f[i-1][j-1]+1);
}
}
printf("%d\n",f[lena][lenb]);
return 0;
}