uva1351 - String Compression 区间DP

Run Length Encoding(RLE) is a simple form of compression. RLE consists of the process for searching for a repeated runs of a single character in a string to be compressed, and replacing them by a single instance of the character and a run count. For example, a string abcccddddddefgggggggggghijk is encoded into a string ab3c6def10ghijk by RLE.

A new compression method similar to RLE is devised and the rule of the method is as follows: if a substringS is repeated k times, replacek copies of S byk(S) . For example, letsgogogo is compressed intolets3(go). The length of letsgogogo is 10, and the length of lets3(go) is 9. In general, the length of k(S) is (number of digits ink ) + (length of S ) + 2 (for `(' and `)'). For example, the length of123(abc) is 8. It is also possible to nest compression, so the substringS may itself be a compressed string. For example,nowletsgogogoletsgogogo could be compressed as a now2(lets3(go)), andnowletsgogogoletsgogogoandrunrunrun could be compressed as now2(lets3(go))and3(run).

Write a program that, for a given string, gives a shortest compressed string using the compression rules as described above.

Input 

Your program is to read from standard input. The input consists of T test cases. The number of test cases T is given in the first line of the input. Each test case consists of a single line containing one string of no more than 200 characters drawn from a lower case alphabet. The length of shortest input string is 1.

Output 

Your program is to write to standard output. Print exactly one line for each test case. For each test case, print the length of the shortest compressed string.

The following shows sample input and output for four test cases.

Sample Input 

4 
ababcd 
letsgogogo 
nowletsgogogoletsgogogo 
nowletsgogogoletsgogogoandrunrunrun

Sample Output 

6 
9 
15 
24

  连续相同的串能用 个数(相同的串)表示,比如gogogo能用3(go)表示,串的长度从6变成了5,letsgogogoletsgogogo能用2(lets3(go))表示。。。给一个串,问用这种方法长度最短变成多少。

  设dp[i][j]为区间[i,j]的串最小长度,dp[i][j],那么dp[i][j]=min(dp[i][k],dp[k+1][j]),i<=k<j。若i,j这个区间能组成n个重复的串,那么dp[i][j]=min(dp[i][j],重复串个数的位数+dp[i][(j-i+1)/n](重复串的最小长度)+2)。

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<sstream>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define INF 0x3f3f3f3f
#define MAXN 210
#define MAXM 510
#define eps 1e-9
#define pi 4*atan(1.0)
#define pii pair<int,int>
using namespace std;
int T,N,dp[MAXN][MAXN];
char str[MAXN];
bool check(int l,int r,int k){
    for(int i=l;i<l+k;i++)
        for(int j=1;i+j*k<=r;j++) if(str[i]!=str[i+j*k]) return false;
    return true;
}
int num(int x){
    int ret=0;
    while(x){
        ret++;
        x/=10;
    }
    return ret;
}
int main(){
    freopen("in.txt","r",stdin);
    scanf("%d",&T);
    while(T--){
        scanf("%s",str);
        N=strlen(str);
        memset(dp,INF,sizeof(dp));
        for(int i=0;i<N;i++) dp[i][i]=1;
        for(int L=1;L<N;L++)
            for(int i=0;i+L<N;i++){
                int j=i+L;
                for(int k=i;k<j;k++) dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]);
                for(int k=1;k<=(j-i+1)/2;k++) if((j-i+1)%k==0){
                    if(check(i,j,k)) dp[i][j]=min(dp[i][j],num((j-i+1)/k)+dp[i][i+k-1]+2);
                }
            }
        printf("%d\n",dp[0][N-1]);
    }
    return 0;
}



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值