动态规划 至多删三个字符

动态规划 至多删三个字符

题目链接
看题目,很明显的动态规划,可以分解成一个个相同的小问题。
先思考dp怎么设定,最多删除三个字符,所以对每个字符串有四种状态,没有删除,删除一个,两个,三个,所以二维的dp两个序号应该一个是表示字符的起点终点啥的,一个表示状态,这里dp[i][j]表示前i的字符,删除了j个字符的可能。
没有删除,那么dp[i][j]=dp[i-1][j],删除了当前那个dp[i][j]=dp[i-1][j-1]。需要注意一些i,j的可能性的判断,然后重点错在这里想了好久,好不容易想到了又不会改,如果出现两个字符相同的情况,比如acdae,删除acd何cda是一样的,一样的,那原本的方法就会重复一倍,那该怎么去重的。
先看重复的部分是哪些,假设k是前一个相同的字符序号,那是不是0到k-1这一段被重复计算了(以上面那个例子为例,相同的部分是xxx acd ae和xxxa cda e,所以前面的xxx是重复的部分),然后两个相同字符中间,加上一个相同字符被删除,那就是删除了i-k个,原本应该删除j个字符,那还需要删除j-(i-k)个字符,故减去dp[k-1][j-(i-k)]

copy的网上大佬的代码,自己写的太复杂,难看懂,自卑
引用网址:https://blog.csdn.net/qq_37275680/article/details/88383950,侵删

#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<set>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
char s[maxn];
ll dp[maxn][4];
 
int main(){
	scanf("%s",s+1);
	int len=strlen(s+1);
	dp[0][0]=1;  //讲真,这里赋值为1还是挺疑惑的
	for(int i=1;i<=len;i++){
		for(int j=0;j<=3;j++){
			if(i<j) break; //前i个都不够删肯定不行呀
			dp[i][j]=dp[i-1][j];  //第i位字符不删 
			if(j>=1) dp[i][j]+=dp[i-1][j-1];  //第i位字符删
			
			for(int k=i-1;k>=1&&i-k<=j;k--){
				if(s[k]==s[i]){
					dp[i][j]-=dp[k-1][j-(i-k)];
					break;
				}
			}
		}
	}
	ll res=0;
	for(int i=0;i<=3;i++){
		res+=dp[len][i];
	}
	printf("%lld\n",res);
	return 0;
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值