经典的最长公共子序列模型。
我们设 (dp_{i,j}) 表示 (a_{1...i}) 与 (b_{1...j}) 匹配上所需的最少操作数。
考虑删除操作,我们将 (a_i) 删除后 (a_{1...i}) 就与 (b_{1...j}) 匹配上了,说明原来 (a_{1...i-1}) 与 (b_{1...j}) 就是匹配上的,转移方程就是 (dp_{i,j}=dp_{i-1,j}+1)。
插入操作与删除操作同理,转移方程是 (dp_{i,j}=dp_{i,j-1}+1)。
考虑替换操作,
- 如果 (a_i=b_j),则 (dp_{i,j}=dp_{i-1,j-1})。
- 如果 (a_i e b_j),则 (dp_{i,j}=dp_{i-1,j-1}+1)。
转移时这 (3) 种情况取 (min) 即可。
边界条件: (dp_{i,0}=i),(dp_{0,i}=i)。
#include <bits/stdc++.h>
using namespace std;
int n, m, ans, dp[1003][1003];
char a[1003], b[1003];
int main()
{
scanf("%d%s", &n, a + 1);
scanf("%d%s", &m, b + 1);
for (int i = 1; i <= n; i+=1) dp[i][0] = i;
for (int i = 1; i <= m; i+=1) dp[0][i] = i;
for (int i = 1; i <= n; i+=1)
for (int j = 1; j <= m; j+=1)
{
dp[i][j] = min(dp[i][j - 1] + 1, dp[i - 1][j] + 1);
if (a[i] == b[j]) dp[i][j] = min(dp[i][j], dp[i - 1][j - 1]);
else dp[i][j] = min(dp[i][j], dp[i - 1][j - 1] + 1);
}
cout << dp[n][m] << endl;
return 0;
}