1. 程式人生 > 實用技巧 >1222分割字串

1222分割字串

我們定義 \(dp_i\) 為前 \(i\) 個字元最長分割的數量,我們發現 \(dp_i\) 可以從 \(dp_j\) \((0\leq 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\n",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;
}