Message(codeforces)

Message

问题:给字符串A,字符串B。有三种操作:1,在字符串的前端或后端加上一个字符2,删掉前端或后端一个字符,改变字符串中间一个字符。求将一个A的子串变成B最少的操作数。

我们要求A一个子串,和B的子串有着最大匹配
说一下最大匹配:这个可能是和B的子串相同,也有可能是和B的子串在中间有几个位置不同其他都相同
我们再用B的长度减去最大匹配中相同的字符个数,得到答案。

我见了两种解法。都写写吧。

暴力

借鉴大佬博客 Orz
两遍暴力,每次二重循环求一个串对另一个串的匹配
A:abc
B:bd
匹配过程:
a-b,b-d
b-b,c-d
c-b
(如果还不太清楚就去看看上面的博客)

#include<bits/stdc++.h>
using namespace std;
char A[2010], B[2010];
int dp[2010][2010]; 
int main() {
	int ans = 0, idx = 0, lena, lenb, u = 0, v = 0;
	A[0] = B[0] = 1; 
	scanf("%s%s", &A[1], &B[1]);
	lena = strlen(A), lenb = strlen(B);
	for(int i=1; i<lena; i++) {
		u = (A[i] == B[1]);
		for(int j=1; j+1<lenb&&i+j<lena; j++) {
			u += (A[i+j]==B[j+1]);
		}
		v = max(v, u);
	}
	for(int i=1; i<lenb; i++) {
		u = (B[i] == A[1]);
		for(int j=1; j+1<lena&&i+j<lenb; j++) {
			u += (B[i+j] == A[j+1]); 
		}
		v = max(v, u);
	}
	printf("%d", lenb-v-1);
	return 0;
}

动态规划

就解释代码吧

#include<bits/stdc++.h>
using namespace std;
char A[2010], B[2010];
int dp[2010][2010]; 
int main() {
	int ans = 0, idx = 0, lena, lenb, u, v;
	A[0] = B[0] = 1; 
	scanf("%s%s", &A[1], &B[1]);
	lena = strlen(A), lenb = strlen(B);
	for(int i=1; A[i]; i++) {
		for(int j=1; B[j]; j++) {
			ans = max(ans, dp[i][j] = dp[i-1][j-1] + (A[i] == B[j]));
		}
	}
	printf("%d", lenb-ans-1);
	return 0;
}

ans = max(ans, dp[i][j] = dp[i-1][j-1] + (A[i] == B[j]));
dp[i][j]是从dp[i-1][j-1]得到的。我们可以打印dp数组观察最大匹配;
举个例子:A:abcd,B:acc;

dpacc
a100
b010
c012
d001

我们可以发现最大匹配是A:abc,B:acc,相同字符数为2。
解决怎样在中间改变使最少操作数的问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值