我们定义 (dp_i) 为前 (i) 个字符最长分割的数量,我们发现 (dp_i) 可以从 (dp_j) ((0leq j < i)) 转移过来,并且发现使得 (j) 尽可能大,可以使得往后的转移条件更容易到达(不会表述)
所以我们只需要 (n^2) 就可以辣!
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int read()
{
int a = 0,x = 1;
char ch = getchar();
while(ch > '9' || ch < '0'){
if(ch == '-') x = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
a = a*10 + ch-'0';
ch = getchar();
}
return a*x;
}
const int N=6e2+7;
char s[N];
int dp[N],n;
int sum[N][30];
int f[N][30];
int main()
{
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
scanf("%s",s+1);
n = strlen(s+1);
for(int i = 1;i <= n;i ++){
for(int j = 0;j < 26;j ++){
sum[i][j] = sum[i-1][j]+(s[i]-'A'==j);
}
}
for(int i = 1;i <= n;i ++){
for(int j = i-1;j >= 0;j --){
bool flag = 0;
for(int k = 0;k < 26;k ++){
if(sum[i][k]-sum[j][k] < f[j][k]) flag = 1;
}
if(flag) continue;
dp[i] = dp[j]+1;
// printf("%d -> %d
",j,i);
for(int k = 0;k < 26;k ++){
f[i][k] = sum[i][k]-sum[j][k];
}
break;
}
}
printf("%d",dp[n]);
return 0;
}