最短编辑距离——线性dp

902. 最短编辑距离 - AcWing题库

刚拿到题感觉无从下手。看了讲解之后才领悟了一丢丢。既然题目是问操作次数的最小值,那么我们就把每一次可以进行的操作分一下类。

 

首先还是按照y总的方法,先分析出状态表示。因为题中问的是将A变成B需要的操作次数,所以我们的状态表示可以是为了让A的前i个字符与B的前j个字符相同的操作次数。求的是最小值min。

对于状态计算,我们可以把f [ i , j ]按照操作的方式进行划分。dp都是分析该状态下最后一个不同的操作。

1.删除–将字符串 A中的某个字符删除:

  注意dp分析的是最后一个不同的操作,已经默认前面的都是最优状态了。所以对于删除操作,我们已经默认A的前i-1个字符与B的前j个字符相同了,此时操作加一,就是删除操作了。

  因此f[i,j]=f[i-1,j]+1。

2.插入–在字符串 A的某个位置插入某个字符:

  对于插入操作,我们默认前i与j-1相同,现在只需要插入一个字符,使得第i个字符(新插入的字符)与第j个字符相等即可。

  因此f[i,j]=f[i][j-1]+1。

3.替换–将字符串 A 中的某个字符替换为另一个字符:

  对于插入操作,我们已经默认前i-1与j-1相同,只需要将第i个字符替换成和第j个字符相同的字符即可

  因此f[i,j]=f[i-1][j-1]+1

4.什么也不做

  如果第i字符与第j字符相等,那就什么也不做,操作次数不变

  因此f[i,j]=f[i-1,j-1]

 

但是我们还要考虑边界问题。当j=0的时候,表示的含义是前i个字符要与0个字符匹配相同,也就是要把前i个字符全部删除,而全部删除的操作次数为i次。因此刚开始的时候应该遍历初始化f[i][0]=i;当i=0的时候,表示的含义是前0个字符与前j的字符相匹配,也就是插入j个字符,操作次数为j次。因此刚开始的时候应该遍历初始化f[0][j]=j

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N=1e3+100;
 4 char a[N],b[N];
 5 int f[N][N];
 6 int main()
 7 {
 8     int n,m;
 9     scanf("%d%s",&n,a+1);
10     scanf("%d%s",&m,b+1);
11     for(int i=1;i<=n;i++)f[i][0]=i;        //全部删除
12     for(int i=1;i<=m;i++)f[0][i]=i;        //全部插入
13     
14     for(int i=1;i<=n;i++)
15     {
16         for(int j=1;j<=m;j++)
17         {
18             f[i][j]=min(f[i][j-1],f[i-1][j])+1;
19             if(a[i]==b[j])f[i][j]=min(f[i][j],f[i-1][j-1]);
20             else f[i][j]=min(f[i][j],f[i-1][j-1]+1);
21         }
22     } 
23     
24     printf("%d\n",f[n][m]);
25     return 0;
26 }
View Code

 

posted @ 2022-03-28 11:44  wellerency  阅读(35)  评论(0编辑  收藏  举报