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]);
}