bzoj1068[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比较明显。不过第一个例子在哪里……

我们很容易就能想到记dp[i][j]为从i到j的最短压缩长度。但是中间的M使得它不好转移。因此我们再用一维。记dp[i][j][m]表示从i到j,中间是否有M的最短压缩长度。其中,m为0/1,m=0时中间没有M,否则有。最初时,dp[i][j][m]=j-i+1。当m=1时,我们可以得到

dp[i][j][m]=dp[i][k][1]+dp[k+1][j][1]+1(i≤k<j)。

其中的+1是因为需要第k位的后面需要插入一个M使得前面与后面不会互相干扰。

因此对于任意的m,我们还可以只压缩前面那一段。因此有如下方程

dp[i][j][m]=min(dp[i][j][m],dp[i][k][m]+j-k)(i≤k<j)

当前后两段完全相同,并且中间均没有M的时候,我们可以把后面的一段替换为R。因此我们有

dp[i][j][m]=min(dp[l][r][m],dp[l][(l+r)/2][0]+1)

最后dp[0][n-1][1]即为答案

代码

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 #include<cmath>
 7 using namespace std;
 8 char ch[110];
 9 int dp[60][60][2];
10 bool used[60][60][2];
11 int len,ans;
12 bool fold(int l,int r){
13     int dis=r-l+1;
14     if(dis&1)  return false;
15     dis=dis/2;int i;
16     for(i=l;i<=(l+r)/2;++i){
17         if(ch[i]!=ch[i+dis])  return false;
18     }
19     return true;
20 }
21 int dfs(int l,int r,int m){
22     int dis=r-l+1;
23     if(dis==1)  return 1;
24     if(used[l][r][m])  return dp[l][r][m];
25     used[l][r][m]=1;
26     int i,j;
27     if(m){
28         for(i=l;i<r;++i){
29             dis=min(dis,dfs(l,i,1)+1+dfs(i+1,r,1));
30         }
31     }
32     for(i=l;i<r;++i){
33         dis=min(dis,dfs(l,i,m)+r-i);
34     }
35     if(fold(l,r)){
36         dis=min(dis,dfs(l,(l+r)/2,0)+1);
37     }
38     dp[l][r][m]=dis;
39     return dis;
40 }
41 int main(){
42     scanf("%s",ch);
43     len=strlen(ch);
44     ans=dfs(0,len-1,1);
45     printf("%d\n",ans);
46     return 0;
47 }

 

posted @ 2018-06-16 22:07  lazytear  阅读(144)  评论(0编辑  收藏  举报