7-3 编辑距离问题 (30 分)
设A和B是2个字符串。要用最少的字符操作将字符串A转换为字符串B。这里所说的字符操作包括 (1)删除一个字符; (2)插入一个字符; (3)将一个字符改为另一个字符。 将字符串A变换为字符串B所用的最少字符操作数称为字符串A到 B的编辑距离,记为d(A,B)。 对于给定的字符串A和字符串B,计算其编辑距离 d(A,B)。
第一行是字符串A,文件的第二行是字符串B。
提示:字符串长度不超过2000个字符。
输出编辑距离d(A,B)
在这里给出一组输入。例如:
fxpimu
xwrs
在这里给出相应的输出。例如:
5
算法思路:
这道题我们通过DP求解,首先设一个dp数组,dp[i][j]表示字符串A的长度为i的前缀与字符串长度为j的前缀的编辑距离。我们对这两个前缀的末尾字符进行操作,首先我们删除A的末尾字符和在B的末尾字符前插入一个字符是等价的,我们可以看做操作之后的两个字符是匹配的,若A被删除,那么就轮到它的前一个字符参与操作,若B前插入,那么A的末尾被匹配,B的原末尾依旧存在,所以其实等价,有dp[i][j] = dp[i - 1][j] + 1,同理。反过来也有 dp[i][j] = dp[i][j - 1] + 1。
对于修改字符的情况,修改后两者必能匹配。都轮到前一个,但如果原本就相等,那么就可省去修改的操作,所以有dp[i][j] = dp[i - 1][j - 1] + flag,其中若A[i] == B[j], flag = 0;A[i] != B[i], flag = 1;最后取这三个值的最小值即可
AC代码:
#include<iostream> #include<stdio.h> #include<string.h> using namespace std; int n, ans, len1, len2; int dp[2050][2050]; char a[2050], b[2050]; int main(){ scanf("%s",a + 1); scanf("%s",b + 1); len1 = strlen(a + 1); len2 = strlen(b + 1); for(int i = 0; i <= len1; ++i){ for(int j = 0; j <= len2; ++j){ if(i == 0 || j == 0){ dp[i][j] = i + j; } else{ dp[i][j] = min(min(dp[i - 1][j] + 1, dp[i][j - 1] + 1), dp[i - 1][j - 1] + (a[i] != b[j])); } } } printf("%d",dp[len1][len2]); return 0; }
时空复杂度分析:
设字符串A长度为m,字符串B长度为n,由于需要一个二维dp数组并对其填表,所以时空复杂度均为O(n*m)。
心得体会:
首先感觉自己对字符串的dp还是不太熟练,不能很好的理清关于字符串的dp的思路,以后需要多加练习。
原文:https://www.cnblogs.com/-y-i-/p/11710857.html