L3-020 至多删三个字符

dp
其他很好理解
就是去重

#include<cstdio>
#include<cmath>
#include<cstring>
#include<vector>
#include<algorithm>
#include<string>
#include<iostream> 
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;
	for(int i = 1; i <= len; ++ i){
		for(int j = 0; j <= 3; ++ j){
			dp[i][j] += dp[i-1][j];//不删 
			if(j)	dp[i][j] += dp[i-1][j-1];//删 
			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)];//向前找相同的,j=几就最多往前找几位 
					break;//显然 j=1 时只需要查看前一位是否相同,若相同就会有重复相同部分:不删前一位删自己和删前一位不删自己,
						//这两部分相同都是dp[k-1][j-(i-k)] i-k = 1 
				}//j = 3 时先查看前一位,前一位相同 就减去,因为前一位已经去重, 所以不需要考虑更前面的
				//如果与前第二位相同,这时候重复的部分就是 不删前第二位,删前一位,删自己和删前第二位,删前一位不删自己
				//所以减去的就应该是 dp[i][j] -= dp[k-1][j-(i-k)] i-k = 2
			}
		}
	}
	printf("%lld\n", dp[len][0] + dp[len][1] + dp[len][2] + dp[len][3]);
}

posted @ 2020-07-23 22:21  wansheking  阅读(122)  评论(0)    收藏  举报