题解 | #计算字符串的编辑距离#暴力递归~备忘录~动态规划
个人思路:看到这题,先别管其他的,暴力递归能不能出来
#暴力递归 #计算s1[0:i+1]和s2[0:j+1]的最小编辑距离 def minDistance(s1,i,s2,j): #base case #(如果两个字符串任意一个为空的情况,最小操作为另一字符串的长度) if i==-1: return j+1 if j==-1: return i+1 """ 字符串编辑处理,从后往前如: 插入:是对s2字符串尾部插入一个字符 删除:是对s1字符串尾部删除一个字符 替换:是对s1字符串尾部变化一个字符 """ if s1[i]==s2[j]: #如果一致,什么都不做比较,往前跳一位 return minDistance(s1,i-1,s2,j-1) else: return min( minDistance(s1,i,s2,j-1)+1,#插入 minDistance(s1,i-1,s2,j)+1,#删除 minDistance(s1,i-1,s2,j-1)+1 #替换 ) while True: try: s1,s2=input(),input() #取s1和s2最大索引 i,j=len(s1)-1,len(s2)-1 print(minDistance(s1,i,s2,j)) except: break进阶思路:可以明显看出有重复子问题,那么对递归进行在优化就可以使用备忘录解决重复子问题
#动态规划(备忘录,递归) def minDistance(s1,i,s2,j,memo): #base case if i==-1: return j+1 if j==-1: return i+1 #提取备忘录,避免重叠子问题 if memo[i][j]!=-1: return memo[i][j] #状态转移方程,存储备忘录 if s1[j]==s2[i]: memo[i][j]=minDistance(s1,i-1,s2,j-1,memo) else: memo[i][j]=min( minDistance(s1,i,s2,j-1,memo)+1,#插入 minDistance(s1,i-1,s2,j,memo)+1,#删除 minDistance(s1,i-1,s2,j-1,memo)+1 #替换 ) return memo[i][j] while True: try: s1,s2=input(),input() m,n=len(s1),len(s2) #初筛化备忘录,注意行列对应 memo=[[-1]*m for _ in range(n)] #s1为横坐标对应n列,s2为纵坐标对应m行n print(minDistance(s1,n-1,s2,m-1,memo)) except: break动态规划(迭代)思路:既然可以递归解决问题(备忘录,自顶向下),那么必然也可以使用迭代(dp)解决。实际dp和备忘录的逻辑基本一致,性能也是差不多的
dp这里需要考虑边界限制,已知当一个字符串为空,那么最小操作距离就是另一字符串的长度,视作做空字符串做插入或删除变空字符串。那么边界就是两个字符串dp[i][0]=i和dp[0][j]=j
那么我们已经就获取了dp[0][0],dp[1][0],dp[0][1]的值,只需要考虑s1[1]和s2[1] (s1和s2开头都插入了空格充作边界)的字符是否相等就可以获得到dp[1][1]的最小操作距离,之后以此类推(从坐标系简化来看就是已知左,左下,右值求右上然后逐渐求出最右上的值)
# 动态规划(迭代) while True: try: s1, s2 = input(), input() n, m = len(s1), len(s2) # 任意字符串为空的情况下,最小操作次数为另一字符串长度 if m * n == 0: print(m + n) # dp二维数组 dp = [[-1] * (m + 1) for _ in range(n + 1)] """ 边界状态初始化 (相当于其中一个字符串为空,最小操作次数为另一字符串长度一样) """ for i in range(n + 1): dp[i][0] = i for j in range(m + 1): dp[0][j] = j # 计算所有dp值 for i in range(1, n + 1): for j in range(1, m + 1): left = dp[i - 1][j]+1 right = dp[i][j - 1]+1 left_down = dp[i - 1][j - 1] if s1[i - 1] != s2[j - 1]: left_down += 1 dp[i][j] = min(left, right, left_down) print(dp[n][m]) except: break
华为机试(python3) 文章被收录于专栏
少壮不努力,老大勤刷题