【TOJ 2510.】 String Compression【DP】

11 篇文章 0 订阅
题意:

给一个字符串,可以把连续相同的部分进行缩写成k(S)的形式,S是一个字符串,k表示有连续相同的S

例如,abgogogogo,可以缩写成ab4(go). 还可以嵌套缩写,比如

“nowletsgogogoletsgogogo”, 缩写成“now2(lets3(go))”,求出最小的长度。

思路:想了好久,开始以为是KMP或者后缀数组的。结果是个区间DP。定义dp[i][j]表示i到j所形成的最小的长度,转移方程为:dp[i][j] = min(dp[i][k], dp[k+1][j]) i <= k < j,因为字符串可以缩写,所以对于【i,j】判断是否可以缩写,即是否可以m个相同的片段(假设长度为L),如果可以dp[i][j] = min(dp[i][j], cal(L)+dp[i][i+L-1]+2).

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 205

char w[N];
int dp[N][N];

int cal(int a) {
    int re = 0;
    while (a) re++, a/=10;
    return re;
}

bool ch(int l, int r, int k) {
    int i, j;
    for (i = l;i < l+k;i++) {
        for (j = k;i+j<=r;j+=k) {
            if (w[i] != w[i+j]) return true;
        }
    }
    return false;
}


int main() {
    int T, k, i, j, len;
    scanf("%d", &T);
    while (T--) {
        scanf("%s", w);
        len = strlen(w);
        memset(dp, 0x3f, sizeof(dp));
        for (i = 0;i < len;i++) dp[i][i] = 1;
        for (k = 2;k <= len;k++) {
            for (i = 0;i <= len-k;i++) {
                int r = i+k-1;
                for (j = i;j < r;j++) {
                    dp[i][r] = min(dp[i][r], dp[i][j]+dp[j+1][r]);
                }
                for (j = 1;j <= k/2;j++) {
                    if (k%j) continue;
                    if (ch(i, r, j)) continue;
                    dp[i][r] = min(dp[i][r], dp[i][i+j-1]+cal(k/j)+2);
                }
            }
        }
        printf("%d\n", dp[0][len-1]);
    }
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值