1090: [SCOI2003]字符串折叠

折叠的定义如下: 1. 一个字符串可以看成它自身的折叠。记作S  S 2. X(S)是X(X>1)个S连接在一起的串的折叠。记作X(S)  SSSS…S(X个S)。 3. 如果A  A’, BB’,则AB  A’B’ 例如,因为3(A) = AAA, 2(B) = BB,所以3(A)C2(B)  AAACBB,而2(3(A)C)2(B)AAACAAACBB 给一个字符串,求它的最短折叠。例如AAAAAAAAAABABABCCD的最短折叠为:9(A)3(AB)CCD。

Input

仅一行,即字符串S,长度保证不超过100。

Output

仅一行,即最短的折叠长度。

Sample Input

NEERCYESYESYESNEERCYESYESYES

Sample Output

14

HINT

 

一个最短的折叠为:2(NEERC3(YES))

思路:

f[i][j] 代表 i 到 j 之间的折叠成最小的长度。 

首先我们要判断是不是有折叠的。 

如果有,判断折叠多少次,因为是有数字在里面的。要计算数字的位数。 

如果不能折叠,有枚举 k 的位置,然后用区间动规做出来。 

 

#include<bits/stdc++.h>
using namespace std;
char s[200];
int tot;
int f[200][200];
bool check(int x, int y,int z){
	if ((y - x + 1) % (z - x +1)) return 0; //是够整除。
	for (int i = x; i <= y; i++)
	if (s[i] != s[(i-x)%(z-x+1) + x]) return 0;	//判断是不是重复的,
	int tt = (y - x + 1) / (z - x + 1); //有多少个重复的。 
	tot = 0;
	while(tt){ //判断有几位数。
		tt /= 10;
		tot++;
	} 
	return 1;
}


int main(){
	int n;
	scanf("%s",s);
	n = strlen(s);
	for (int i = 0; i < n; i++) f[i][i] = 1;
	for (int len = 2; len <= n; len++){
		for (int i = 0; i <= n - len; i++){
			int j = i + len - 1;
			f[i][j] = len; //初始化。
			for (int k = i; k < j; k++){
				if (check(i,j,k))	f[i][j] = min(f[i][j],f[i][k] + 2 + tot); //如果重复。
				f[i][j] = min(f[i][j], f[i][k] + f[k+1][j]); //不重复,直接加起来。
			}
		}
	}
	printf("%d\n",f[0][n-1]);
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值