题目描述
设 A A A 和 B B B是两个字符串。我们要用最少的字符操作次数,将字符串 A A A转换为字符串 B B B。这里所说的字符操作共有三种:
- 删除一个字符;
- 插入一个字符;
- 将一个字符改为另一个字符。
A , B A,B A,B 均只包含小写字母。
输入格式
第一行为字符串 A A A;第二行为字符串 B B B;字符串 A , B A,B A,B 的长度均小于 2000 2000 2000。
输出格式
只有一个正整数,为最少字符操作次数。
输入样例
sfdqxbw
gfdgw
输出样例
4
题解
设字符串
s
1
,
s
2
s1,s2
s1,s2,设
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j] 为
s
1
s1
s1 前
i
i
i 位修改为
s
2
s2
s2 前
j
j
j 位的花费。
状态转移方程(注意
s
t
r
i
n
g
string
string 类是从第
0
0
0 位开始的,所以要判断
s
1
[
i
−
1
]
=
=
s
2
[
j
−
1
]
s1[i-1] == s2[j-1]
s1[i−1]==s2[j−1]):
{
i
f
(
s
1
[
i
−
1
]
=
=
s
2
[
j
−
1
]
)
d
p
[
i
]
[
j
]
=
d
p
[
i
−
1
]
[
j
−
1
]
e
l
s
e
{
i
n
s
e
r
t
:
d
p
[
i
]
[
j
]
=
d
p
[
i
]
[
j
−
1
]
d
e
l
e
t
e
:
d
p
[
i
]
[
j
]
=
d
p
[
i
−
1
]
[
j
]
c
h
a
n
g
e
:
d
p
[
i
]
[
j
]
=
d
p
[
i
−
1
]
[
j
−
1
]
+
1
\begin{cases}if(s1[i-1] == s2[j-1])dp[i][j] = dp[i-1][j-1]\\else\begin{cases}insert:dp[i][j] = dp[i][j-1]\\delete:dp[i][j] = dp[i - 1][j]\\change:dp[i][j]=dp[i-1][j-1]+1\end{cases}\end{cases}
⎩⎪⎪⎪⎨⎪⎪⎪⎧if(s1[i−1]==s2[j−1])dp[i][j]=dp[i−1][j−1]else⎩⎪⎨⎪⎧insert:dp[i][j]=dp[i][j−1]delete:dp[i][j]=dp[i−1][j]change:dp[i][j]=dp[i−1][j−1]+1
解释一下:
- 如果 s 1 s1 s1 第 i i i 位等于 s 2 s2 s2 第 j j j 位,不用修改,此时 d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] dp[i][j] = dp[i-1][j-1] dp[i][j]=dp[i−1][j−1]。
- 如果
s
1
s1
s1 第
i
i
i 位不等于
s
2
s2
s2 第
j
j
j 位,尝试以下操作,使得花费最小:
2.1 在 s 1 s1 s1 第 i i i 位后插入 s 2 s2 s2 第 j j j 位,等效于删除 s 2 s2 s2 第 j j j 位。此时状态转移方程为 d p [ i ] [ j ] = d p [ i ] [ j − 1 ] ; dp[i][j] = dp[i][j-1]; dp[i][j]=dp[i][j−1];
2.2 删除 s 1 s1 s1 第 i i i 位。此时状态转移方程为 d p [ i ] [ j ] = d p [ i − 1 ] [ j ] ; dp[i][j] = dp[i-1][j]; dp[i][j]=dp[i−1][j];
2.3 交换 s 1 s1 s1 第 i i i 位和 s 2 s2 s2 第 j j j 位。此时状态转移方程为 d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] + 1 dp[i][j] = dp[i-1][j-1]+1 dp[i][j]=dp[i−1][j−1]+1。
注意 边界:如果 s 1 s1 s1 或者 s 2 s2 s2 其中一者是空字符串,则需要 s 1 s1 s1 或者 s 2 s2 s2 不为空一方的字符串长度的花费。
代码如下:
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n, m;
const int len = 10010;
const int mod = 1e6+7;
string s1, s2;
int dp[len][len];
int ans(){
for(int i = 1; i <= s1.length(); i++) dp[i][0] = i;
for(int j = 1; j <= s2.length(); j++) dp[0][j] = j;
for(int i = 1; i <= s1.length(); i++)
for(int j = 1; j <= s2.length(); j++){
if(s1[i - 1] == s2[j - 1]) dp[i][j] = dp[i - 1][j - 1];
else dp[i][j] = min(min(dp[i - 1][j] + 1, dp[i][j - 1] + 1), dp[i - 1][j - 1] + 1);
}
return dp[s1.length()][s2.length()];
}
signed main(){
cin >> s1 >> s2;
cout << ans() << endl;
return 0;
}