原题:
状态表示:f[ i ][ j ]
集合:所以把 a 数组的前 i 个项变为 b 数组的前 j 个项的最少操作次数。
状态转移:
① 删除一个数 : f[ i ][ j ] = f[ i - 1][ j ] + 1;(如果删除 a 字符串最后一个字符可以保证两字符串相同的话,说明a字符串的前 i - 1 个项与b字符串的前 j 个相同)
② 增加一个数 : f[ i ][ j ] = f[ i ][ j - 1 ] + 1; (如果增加 a 字符串最后一个字符可以保证两字符串相同的话,说明a字符串的前 i 个项与b字符串的前 j - 1个相同)
③ 替换一个数 :f[ i ][ j ] = f[ i - 1][ j - 1 ] + 1:(如果修改 a 字符串最后一个字符可以保证两字符串相同的话,说明a字符串的前 i - 1 个项与b字符串的前 j - 1个相同)
④ 两字符串相同 : f[ i ][ j ] = f[ i - 1][ j - 1 ];
需要注意的:
①因为我们使用了 i - 1 的下标, 所以我们最后从 1 开始输入遍历,防止数组越界或者不必要的特判;
②当a字符串长度为 0 ,b字符串长度为 j 时, 我们要对 a 进行 j 次添加操作, b 字符串长度为0 时同理;
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
char a[N], b[N];
int f[N][N];
int n, m;
int main()
{
scanf("%d%s",&n, a + 1);
scanf("%d%s",&m, b + 1);
//初始化
for(int i = 1; i <= max(n,m); i ++ ) f[0][i] = f[i][0] = i;
for(int i = 1; i <= n; i ++ )
for(int j = 1; j <= m; j ++ )
f[i][j] = min(min(f[i-1][j] + 1, f[i][j - 1] + 1),f[i - 1][j - 1] + (a[i] != b[j]));
cout << f[n][m];
}