题解【AcWing902】最短编辑距离

题面

经典的最长公共子序列模型。

我们设 \(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\ne 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;
}

猜你喜欢

转载自www.cnblogs.com/xsl19/p/12324020.html