题目大意:
就是给出两个字符串,只能进行增删改操作,问从字符串1转化为字符串2最少需要几步
状态转移方程
dp[i][j] i和j分别表示两个字符串的长度
当s1[i]==s2[j]的时候,说明不用操作,相当于当s1长度为i的时候和s2长度为j的时候不需要进行操作,所以次数和s1长度为i-1和s2长度为j-1的时候相等
所以dp[i][j]=dp[i-1][j-1]
当s1[i]!=s2[j]的时候,说明需要进行一步操作,具体是增删改里面的哪一步,根据下文可以理解
模拟过程
首先需要根据dp数组来进行判断,举下边这个例子
s2\s1 | 空 | s | f | d | q | x | b | w |
空 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
g | 1 | |||||||
f | 2 | |||||||
d | 3 | |||||||
g | 4 | |||||||
w | 5 |
首先先对dp数组进行初始化,先将两个数组的第一个元素s[0]插入一个空以便后面运算
我们就比较容易知道当两个字符串都为空的时候,说明两个字符串相等,进行0步操作就可以完成相等的目的,所以dp[0][0]=0
随后的数据按横行来举例,当值取到s的时候,相当于s1的值是s(本来是没有,现在有了一个元素),所以s2(此时为空)需要变成s1的s,需要进行一步添加操作来变成和s1一样,所以进行一步操作,所以dp[1][0]=1;
同理当s1取到 sf 的时候s2需要进行两步添加操作,所以dp[2][0]=2
同样的可以列举所有横行和竖行来进行初始化
当s1[i]!=s2[j]时,有dp[i][j]=min(dp[i-1][j-1],min(dp[i-1][j],dp[i][j-1]))+1;
初始化完毕后需要进行循环遍历了,因为一开始在字符串s[0]的位置插入了了一个空,所以遍历需要在i=1和j=1进行遍历,当s1[i]!=s2[j]的情况中,说明肯定需要一步操作,dp[i][j]需要在
s1的长度为i-1,s2的长度为j的情况,对应dp[i-1][j]
s1的长度为i,s2的长度为j-1的情况,对应dp[i][j-1]
s1的长度为i-1,s2的长度为j-1的情况,对应dp[i-1][j-1]
三种情况中选择最小的来进行一步操作,三种情况分别代表的含义还是需要回到表格中寻找答案(这个解释自己看的也比较迷惑,不确定自己想的对不对)
具体是增加还是删除看这篇博客可能会好一点
详解编辑距离算法-Levenshtein Distance_BoCong-Deng的博客-优快云博客_编辑距离算法原理
首先是dp[i-1][j]
相当于s1的前i-1位和s2的前j-1位通过dp[i-1][j-1]已经相等了,但是j比i长了一位,所以让i加一位变成dp[i][j],i做了一次增加操作(相当于j减一?)
然后是dp[i][j-1]
同理相当于s1的前i-1位和s2的前j-1位通过dp[i-1][j-1]已经相等了,但是j比i短了一位,加一位j就可以得到dp[i][j],j做了一次增加操作
最后是dp[i-1][j-1]
相当于原本长度为i-1的s1和长度为j-1的s2是相等的,现在s1和s2各加了一位,而且加的还不相等(此处是建立在s1[i]!=s2[j]的基础上才进行判断的)所以需要做一次修改,将两次加的数字修改成一样的
因为s1[i]!=s2[j],所以无论如何都需要做一步操作才能让新增加的重新变为相等的,因为结果要取操作最少的,所以在三个里面选一个最小的加1,就可以得到方程
dp[i][j]=min(dp[i-1][j-1],min(dp[i-1][j],dp[i][j-1]))+1; (当s1[i]!=s2[j])
当s1[i]==s2[j]时,有dp[i][j]=dp[i-1][j-1]
这个也很好理解原本i-1,j-1为了相等操作了dp[i-1][j-1]次,现在s1和s2的长度都加了1,而且加的数值都一样,说明在i-1,j-1长度的基础上不需要进行操作了,直接相等就可以了
模板
string a,b;
cin>>a>>b; //输入数据
a.insert(0,1,' '); //设置首位为空
b.insert(0,1,' '); //设置首位为空
for(int i=0;i<a.size();i++) dp[i][0]=i; //初始化
for(int i=0;i<b.size();i++) dp[0][i]=i; //初始化
for(int i=1;i<=m;i++){ //遍历
for(int j=1;j<=n;j++){
if(a[i]==b[j]){ //相等时
dp[i][j]=dp[i-1][j-1]; //相等的状态转移方程
}else{ //不相等时
dp[i][j]=min(dp[i-1][j],min(dp[i][j-1],dp[i-1][j-1]))+1;
//不相等的状态转移方程
}
}
}
cout<<dp[a.size()-1][b.size()-1]; //输出结果
例题