String Painter题解(区间DP)

题目:

There are two strings A and B with equal length. Both strings are made up of lower case letters. Now you have a powerful string painter. With the help of the painter, you can change a segment of characters of a string to any other character you want. That is, after using the painter, the segment is made up of only one kind of character. Now your task is to change A to B using string painter. What’s the minimum number of operations?

Input

Input contains multiple cases. Each case consists of two lines:
The first line contains string A.
The second line contains string B.
The length of both strings will not be greater than 100.

Output

A single line contains one integer representing the answer.

Sample Input

zzzzzfzzzzz
abcdefedcba
abababababab
cdcdcdcdcdcd
Sample Output

6
7
————————————————

题目来自:
                        
原文链接:https://blog.csdn.net/qq_43472263/article/details/98328616

思路:

先将空白字符串刷成s2,

i从右往左,j从左往右,不考虑s2[i]和s2[j]是否相等的情况下,最坏情况是,dp[i][j] = 1+dp[i+1][j],因为i+1会比i先遍历到,但在按正常顺序的解释应该是先从i刷一遍,再从i+1刷一遍覆盖。(苯人一开始就是没想明白这里,还是题做少了呜呜)

考虑优化情况,如果i、j间有k,使得s2[i] = s2[k],那么就不用先从i单独刷一遍了,所以dp[i][j] = min(dp[i][j],dp[i+1][k]+dp[k+1][j])

然后将s1与s2进行比较,新开数组res[i],表示前i个字符的最小操作数。res[i] = dp[0][i-1]。

如果s1[i] = s2[i],那么直接res[i] = res[i-1]。如果不相等,那么就在0-i区间内遍历,找一个j,使res[i] = min(res[i],res[j]+dp[j][i-1]),

最后返回res[len]。

代码:

#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;

int res[101];
int main(){
	string s1,s2;
	cin>>s1>>s2;
	int len = s1.length();
	int dp[101][101];
	memset(dp,0,sizeof(dp));//初始化dp数组为0;
	//先将空白字符串刷成s2
	for(int j = 0;j<len;j++){
		for(int i = j;i>=0;i--){
				dp[i][j] = dp[i+1][j] + 1;//相当于倒着推,先从i到j刷一层,再将i+1到j刷成s2;
			for(int k = i+1;k<=j;k++){
				 if(s2[i] == s2[k]){
					 dp[i][j] = min(dp[i][j],dp[i+1][k]+dp[k+1][j]);
				 }
			 }
		}
	}
	//根据空白字符串,筛选出s1与s2相同字符的情况,减少操作数
	for(int i = 1;i<=len;i++){
		res[i] = dp[0][i-1];//res[i]为前i个字符刷为s2
	}
	for(int i = 1;i<=len;i++){
		if(s1[i-1] == s2[i-1]){
			res[i] = res[i-1];
		}else{
			for(int j = 1;j<i;j++){
				res[i] = min(res[i],res[j]+dp[j][i-1]);
			}
		}
	}
	cout<<res[len]<<endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值