编辑距离
设
A
A
A和
B
B
B是两个字符串。我们要用最少的代价(或者字符操作次数),将字符串
A
A
A转换为字符串
B
B
B。字符操作有三种
1.插入一个字符,所需代价为
x
x
x
2.删除一个字符,所需代价为
y
y
y
3.将一个字符改为另一个字符,即替换,所需代价为
z
z
z
输入
A
B
AB
AB两个字符串,输出代价
思路
删除:可以看做把
A
A
A串最后一个字符删去后不再考虑这个字符 所以
d
p
[
i
]
[
j
]
=
m
i
n
(
d
p
[
i
]
[
j
]
,
d
p
[
i
−
1
]
[
j
]
+
x
)
dp[i][j]=min(dp[i][j],dp[i-1][j]+x)
dp[i][j]=min(dp[i][j],dp[i−1][j]+x)
插入:可以看做与
B
B
B串最后一个字符抵消后不再考虑这个字符 所以
d
p
[
i
]
[
j
]
=
m
i
n
(
d
p
[
i
]
[
j
]
,
d
p
[
i
]
[
j
−
1
]
+
y
)
dp[i][j]=min(dp[i][j],dp[i][j-1]+y)
dp[i][j]=min(dp[i][j],dp[i][j−1]+y)
替换:可以看做删和加的集合 抵消了
A
B
AB
AB串最后的两个字符 所以
d
p
[
i
]
[
j
]
=
m
i
n
(
d
p
[
i
]
[
j
]
,
d
p
[
i
−
1
]
[
j
−
1
]
)
dp[i][j]=min(dp[i][j],dp[i-1][j-1])
dp[i][j]=min(dp[i][j],dp[i−1][j−1])
代码
ll n,m,p;
char s[maxn],t[maxn];
ll dp[maxn][maxn];//将s换为t所需要的最少次数
int main(){
scanf("%s%s",s+1,t+1);
ll x,y,z;
scanf("%lld%lld%lld%lld",&x,&y,&z);
ll n,m;
n=strlen(s+1);
m=strlen(t+1);
///初始化
for(int i=1;i<=m;i++){//此时,s为空,则需添加i个字母,花费i*x
dp[0][i]=i*x;
}
for(int i=1;i<=n;i++){//此时,t为空,则需删除i个字母,花费i*y
dp[i][0]=i*y;
}
//将s[1...i]经过最少次数的操作转化为t[1...j]
//在此之前以最小次数k的操作,使得现在的s,t只需再做一次操作或者不做操作
// 就可以使s[1...i]转换到t[1...j],有三种情况
//s[1...i]转换为t[1...j-1] 添加
//s[1...i-1]转换为t[1...j] 删除
//s[1...i-1]转换为t[1...j-1] 替换
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
dp[i][j]=min(dp[i-1][j]+y,dp[i][j-1]+x);
if(s[i]==t[j]){
dp[i][j]=min(dp[i][j],dp[i-1][j-1]);
}
else{
dp[i][j]=min(dp[i][j],dp[i-1][j-1]+z);
}
}
}
printf("%lld\n",dp[n][m]);
}