以下部分来自这里
给定两个字符串word1和word2,找到将word1转换为word2所需的最小步骤数。 (每个操作计为1步)。
您对单词允许以下3种操作:
a)插入字符
b)删除字符
c)替换字符
思路:
dp[i][j]指把word1[0..i - 1]转换为word2[0..j - 1] 的最小操作数。
边界条件:
dp[i][0] = i; 从长度为 i 的字符串转为空串 要删除 i 次
dp[0][j] = j. 从空串转为长度为 j 的字符串 要添加 j 次
一般情况:
如果word[i - 1] == word2[j - 1],则dp[i][j] = dp[i - 1][j - 1],因为不需要进行操作,即操作数为0.
如果word[i - 1] != word2[j - 1],则需考虑三种情况,取最小值:
Replace word1[i - 1] by word2[j - 1]: (dp[i][j] = dp[i - 1][j - 1] + 1 (for replacement));
Delete word1[i - 1]: (dp[i][j] = dp[i - 1][j] + 1 (for deletion));
Insert word2[j - 1] to word1[0..i - 1]: (dp[i][j] = dp[i][j - 1] + 1 (for insertion)).
再来看一道牛客寒假训练的题:
链接:https://ac.nowcoder.com/acm/contest/327/G
来源:牛客网
题目描述
一天,处女座在牛客算法群里发了一句“我好强啊”,引起无数的复读,可是处女座发现复读之后变成了“处女座好强啊”。处女座经过调查发现群里的复读机都是失真的复读机,会固定的产生两个错误。一个错误可以是下面的形式之一:
1. 将任意一个小写字母替换成另外一个小写字母
2. 在任意位置添加一个小写字母
3. 删除任意一个字母
处女座现在在群里发了一句话,他收到了一个回应,他想知道这是不是一个复读机。
输入描述:
两行 第一行是处女座说的话s 第二行是收到的回应t s和t只由小写字母构成且长度小于100
输出描述:
如果这可能是一个复读机输出”YES”,否则输出”NO”
示例1
输入
abc abcde
输出
YES
说明
abc->abcd->abcde
示例2
输入
abcde abcde
输出
YES
说明
abcde->abcdd->abcde
备注:
只要能经过两步变换就从s得到t就有可能是复读机。
这题就是实打实的模板题了,说起牛客寒假训练,氛围简直不太好,估计初中生太多,切记莫在群里水群,因为总会有人私信问你写法,甚至有的人有偿求代码。我是不知道这样有什么好处,有什么坏处。大概对别人不公平吧。别在这种训练赛的时候表现的像一位大佬,一到省赛、区域赛反而是打铁。会就是会,不会就是不会。
这样的情况最容易被带歪榜了,明明某个题比这个题简单,但是不知为何这个题ac人贼高,然后就跟榜看这题,这种题往往是得出结论即可,没什么算法。某个题需要简单的构造即可。由于问别人结论比自己构造简单多了,导致歪榜了。
#include<bits/stdc++.h>
using namespace std;
int dp[1010][1010];
char s1[1010];
char s2[1010];
int main()
{
scanf("%s%s",s1,s2);
int l1=strlen(s1);
int l2=strlen(s2);
if(abs(l1-l2)>2)
{
printf("NO");
return 0;
}
for(int i=0;i<=l1;i++)
for(int j=0;j<=l2;j++)
dp[i][j]=0;
for(int i=1;i<=l1;i++) dp[i][0]=i;
for(int j=1;j<=l2;j++) dp[0][j]=j;
for(int i=1;i<=l1;i++)
for(int j=1;j<=l2;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,dp[i][j-1]+1),dp[i][j]=min(dp[i][j],dp[i-1][j-1]+1);
}
int gc=dp[l1][l2];
if(gc==0||gc==2||gc==1)
{
printf("YES\n");
}
else printf("NO\n");
// cout<<dp[l1][l2]<<endl;
}