题目:
设A和B是两个字符串。我们要用最少的字符操作次数,将字符串A转换为字符串B。这里所说的字符操作共有三种:
1. 删除一个字符;
2. 插入一个字符;
3. 将一个字符改为另一个字符。
对任给的两个字符串A和B,计算出将字符串A变换为字符串B所用的最少字符操作次数。Input
第一行为字符串A;第二行为字符串B;字符串A和B的长度均小于200。
Output
只有一个正整数,为最少字符操作次数。
Sample Input
abcf
bcfe
Sample Output
2
一开始拿到题没有思路的话举个例子就知道了,下图为dp[][]的转换过程,th(替换),sa(相同),de(删除),当然转换方法不止一种,例如当j(列)=3,i(行)=1时:两者(car和a)相互转换可以将r和c删除(两步),而删除c的步骤在转换i=0(空),j=1(c)时我们就早已知道要删除c,所以dp[1][0]=1。这也就是动态规划前一步为后一步服务的思想,由此我们可以推断出dp[i][j]的含义为:使A的第i个元素和B的第j个元素相同时所需要的最小步骤。若觉得理解不深刻可自行举两个简单的例子。
再看表格,当A串和B串第i,j个字母相同时(注意,此时A串和B串前面的字母一定相同,因为这就像多米诺骨牌一样,我们已经使得前面的骨牌倒下,并计算出了最小步骤。)我们直接取两者的前一步dp[i-1][j-1]即可
其他情况,dp[i][j] = min(dp[i-1][j], dp[i - 1][j - 1] dp[i][j-1])+1(蓝桥杯官方写法),为什么是取这三个方向呢,对照表格可以看到dp[i-1][j]相当于将”atn“删除一个字符以求得和A串相等;dp[i - 1][j - 1]相当于前面都相同,唯有这个不同,所以要修改;dp[i][j-1]相当于将”cartoon“删除一个字符以求得和A串相等;
(我感觉这个可以再优化,或许只需dp[i][j]=dp[i - 1][j - 1] +1即可,我举了两个例子是对的,或许有反例)
可运行代码如下(这也是蓝桥杯官方写法):
def transStrMinStep(A,B):
A_len=len(A)-1 #列
B_len=len(B)-1
dp=[[0 for _ in range(B_len+1)] for _ in range(A_len+1)]
for i in range(1,A_len+1): #行,从1赋值是因为dp[0][0]已经初始化成0,没必要再初始化了
dp[i][0]=i
for j in range(1,B_len+1): #列
dp[0][j]=j
for i in range(1,A_len+1):
for j in range(1,B_len+1):
if A[i] != B[j]:
dp[i][j]=(min(dp[i-1][j-1],dp[i-1][j],dp[i][j-1])+1)
if A[i] == B[j]:
dp[i][j] = dp[i - 1][j - 1]
return dp[-1][-1]
A=input()
B=input()
A=''+A
B=''+B
print(transStrMinStep(A, B))