8
28
2015
0

1068: [SCOI2007]压缩

1068: [SCOI2007]压缩

Description

给一个由小写字母组成的字符串,我们可以用一种简单的方法来压缩其中的重复信息。压缩后的字符串除了小写字母外还可以(但不必)包含大写字母R与M,其中M标记重复串的开始,R重复从上一个M(如果当前位置左边没有M,则从串的开始算起)开始的解压结果(称为缓冲串)。 bcdcdcdcd可以压缩为bMcdRR,下面是解压缩的过程:

 

另一个例子是abcabcdabcabcdxyxyz可以被压缩为abcRdRMxyRz。

Input

输入仅一行,包含待压缩字符串,仅包含小写字母,长度为n。

Output

输出仅一行,即压缩后字符串的最短长度。

Sample Input

bcdcdcdcdxcdcdcdcd

Sample Output

12

HINT

 

在第一个例子中,解为aaaRa,在第二个例子中,解为bMcdRRxMcdRR。 

【限制】 

100%的数据满足:1<=n<=50 100%的数据满足:1<=n<=50

 

 

 

 

区间DP

对于每个区间l,r,我们分 压缩后 含M或不含M 两种情况(用t=1或0表示)。。。

对于每一个区间(不分含不含M的情况),

    我们可以把区间前一段压缩(含不含M 视整个区间是否含M),后一段作为缓冲串

对于压缩后含M的情况,

    我们可以把区间分为两段都拿去压缩,然后在压缩完的两段间加一个M。。。

特殊的,对于前半段与后半段相同的区间,

    我们可以在 前半段不含M的压缩串后加R

    (即压缩串长度可为 前半段不含M的压缩串长度+1)

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define MaxN 51
char s[MaxN];
int len,f[MaxN][MaxN][2];
bool check(int l,int r){
    int len=r-l+1;
    if (len%2) return false;
    int mid=(l+r)/2;
    int j=mid+1;
    for (int i=l;i<=mid;++i){
		if (s[i]!=s[j]) return false;
		++j;
    }
    return true;
}
int calc(int l,int r,int t){
    if (l==r) f[l][r][t]=1;
    if (f[l][r][t]) return f[l][r][t];
	int ans=r-l+1;
	for (int i=l;i<r;++i){		
		ans=min(ans,calc(l,i,t)+r-i);
		if (t) 
		    ans=min(ans,calc(l,i,1)+calc(i+1,r,1)+1);
	}
    if (check(l,r))
		ans=min(ans,calc(l,(l+r)/2,0)+1);
	f[l][r][t]=ans;
	return f[l][r][t];
}
int main(){
	scanf("%s",s+1);
	len=strlen(s+1);
	printf("%d\n",calc(1,len,1));
}
Category: BZOJ | Tags: DP bzoj | Read Count: 334

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com