题意:
思路:
(1)状态:
dp[i][j]表示前i个字符,删除j个的答案数量
(2)状态转移方程
删或者是不删
删掉:dp[i][j] = dp[i - 1][j - 1] + dp[i][j];
不删:dp[i][j] = dp[i][j] + dp[i - 1][j];
(3)去重
那么我们怎么去重呢?因为我们是从1开始的,遍历到后面的时候前面一定是去完重的。
如果在j的范围内出现重复现象,dp[i][j] = dp[i][j] - dp[k - 1][j - (i - k)];
代码实现:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn = 2e6 + 5;
char s[maxn];
ll dp[maxn][5];
int main(){
scanf("%s",s + 1);
int n = strlen(s + 1);
dp[0][0] = 1;
for(int i = 1;i <= n;i++){
for(int j = 0;j <= 3;j++){
if(j > 0) dp[i][j] += dp[i - 1][j - 1];
dp[i][j] += dp[i - 1][j];
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 ans = dp[n][0]+dp[n][1]+dp[n][2]+dp[n][3];
printf("%lld\n",ans);
return 0;
}