题目:
编辑距离问题,给定两个字符串str1和str2,str1变成str2的代价是多少,比如 1)保留:0 , 2)删除:10, 3)添加:5, 4)替换:3
接收两个字符串,代价值int,返回最小距离
分析:
“ab1c”变成“abc”的编辑代价是删除“1”,即10,“abcd”变成“abce”的代价是3
str1:=“aab151” str2:=“aab51” dc:=10 ic:=5 rc:=3
代码如下:
package main
import (
"fmt"
"math"
)
//编辑距离问题,给定两个字符串str1和str2,str1变成str2的代价是多少,比如 1)保留:0 , 2)删除:10, 3)添加:5, 4)替换:3
//“ab1c”变成“abc”的编辑代价是删除“1”,即10,“abcd”变成“abce”的代价是3
//接收两个字符串,代价值int,返回最小距离
//str1:="aab151" str2:="aab51" dc:=10 ic:=5 rc:=3
func minditences(str1,str2 string,dc,ic,rc int) int{
var dp [][]int
if len(str1)==0 && len(str1)==0{
return 0
}
//建一张表,列是str1,行是str2
for i :=0;i<len(str1)+1;i++{
tmp:=make([]int,len(str2)+1)
dp=append(dp,tmp)
}
dp[0][0]=0
//假如str1是长度是0,str1如何变成str2。添加,添加一个长度是ic,i个就是i*ic
for i:=0;i<=len(str2);i++{
dp[0][i]=ic*i
}
//假如str2是长度是0,str1如何变成str2。删除,删除一个长度是dc,i个就是i*dc
for j:=0;j<=len(str1);j++{
dp[j][0]=dc*j
}
//分支1,str1=abedf str2=abcd,str1要变成str2,先将前面部分abed变成abcd,再删去e,即dp[i-1][j]+dc
//分支2,str1=qwe str2=que3,str1要变成str2先将qwe变成que,再加上3,即dp[i][j-1]+ic
//分支3,s1与s2最后的字符相同,只需要将s1前面字符变成与s2一致即可,dp[i-1][j-1]+保留代价0
//分支4,s1与s2最后一个不相同,前面也不相同,替换代价dp[i-1][j-1]+替换代价
for i:=1;i<=len(str1);i++{
for j:=1;j<=len(str2);j++{
// if i>len(str1){
// dp[i][j]=dp[i-1][j]+dc
// }
// if i<len(str1){
// dp[i][j]=dp[i-1][j]+ic
// }
//分支3,4
//矩阵中一点对应的str1和str2 的index上的字符相同,就填充上一个节点的值不变,如dp[3][3]对应到就是str1[2],str2[2]
if str1[i-1]==str2[j-1]{
dp[i][j]=dp[i-1][j-1]//保留
}else{
//矩阵中一点对应的str1和str2 的index上的字符不同,就填充上一个节点的值+替换的值
dp[i][j]=dp[i-1][j-1]+rc//替换
}
//分支1,2,上面if else已经判定了保留还是rc,下面其实是判断四种情况谁的代价最小
//math.min接收float64,在转换的时候注意精度丢失问题
dp[i][j]=int(math.Min(float64(dp[i][j]),float64(dp[i][j-1]+ic)))//增
dp[i][j]=int(math.Min(float64((dp[i][j])),float64(dp[i-1][j]+dc)))//删
}
}
fmt.Println(dp)
return dp[len(str1)][len(str2)]
}
func main(){
str1:="aab151"
str2:="aab51"
fmt.Println(minditences(str1,str2,10,5,3))
}
画出图来:
还是没搞明白返回最后一个位置的值就是最终答案,先记录下来
似乎是合理的,如果先替换前面再删除代价是3+3+10=16,
如果只删除str1的第三个字符“1”,代价为10,代价最小,