字符串动态规划(从一个字符串变成另一个字符串)

以下部分来自这里

给定两个字符串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;
}

猜你喜欢

转载自blog.csdn.net/qq_41286356/article/details/86647553