题目描述
设A和B是两个字符串。我们要用最少的字符操作次数,将字符串A转换为字符串B。这里所说的字符操作共有三种:
1.删除一个字符;
2.插入一个字符;
3.将一个字符改为另一个字符。A,B均只包含小写字母。
输入格式
第一行为字符串A;第二行为字符串B;字符串A,B的长度均小于2000。
输出格式
只有一个正整数,为最少字符操作次数。
输入
sfdqxbw
gfdgw
输出
4
一般问题都是给定两个字符串通过增删改吧第一个字符串转换为第二个字符串的最短编辑昌都市是多少。看到这种题如果不是看题目的标签我很可能以为是多源最短路问题,我蒟蒻一个也不知道用多源最短路能不能做。我想的方法就是动态规划。
之前学01和完全都是先确定二维数组表示含义,写出递推式,根据递推式写出状态转移方程。
最短编辑距离问题也是按照这个步骤来。因为我们的字符串可以通过插入、删出查找,来转变为另一个字符串所以我们的dp[i][j]就需要从三个方法中找出最短的一条来操作。
1.确定状态变量: dp[i][j] 表示a字符串从第一个字符变换到b字符串的1到m
如果对于的字符相等 则:f[i][j] =f[i-1][j-1]
2.确定表达式
(1)修改操作:把a[i]改为b[j] 即f[i][j]=f[i-1][j-1]+1
f[i-1][j-1]表示a和b字符串前i-1个字符都想相等了。+1表示只需要修改下一个就完全相等。这个表达式的意思就是当我把前面的字符修改完之后只需要再修改一次就完成了。
(2)插入操作:在a[i]后插入b[j] 即f[i][j] = f[i][j-1]+1
f[i][j-1]表示a字符串前i个字母与吧b字符串的前j-1个字符都相等了,+1我们只需要再插入一个字符就完全相等了
(3)删除操作:删除a[i] 即 f[i][j]= f[i-1][j]+1
f[i-1][j]表示a字符串的前i-1项都与b的前项相同,说明a现在比b多一个字符,+1表示删除这个字符加一次操作
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 2000;
int dp[N][N];
string s1,s2;
int n,m;
int main(){
cin>>s1>>s2;
m = s1.size();
n = s2.size();
// cout<<m<<" "<<n<<endl;
//边界
for(int i = 0;i<=m;i++)dp[i][0] = i;
for(int j = 0;j<=n;j++)dp[0][j] = j;
for(int i = 1;i<=m;i++){
for(int j = 1;j<=n;j++){
if(s1[i-1] == s2[j-1]){
dp[i][j] = dp[i-1][j-1];
}else{
dp[i][j] = min(dp[i-1][j-1],min(dp[i][j-1],dp[i-1][j]))+1;
}
}
}
cout<<dp[m][n];
return 0;
}