BZOJ1068 [SCOI2007]压缩 【区间dp】

题目

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

输入格式

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

输出格式

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

输入样例

bcdcdcdcdxcdcdcdcd

输出样例

12

提示

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

【限制】

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

题解

我们可以看做最左端有一个M
我们设\(f[l][r][0|1]\)表示区间\([l,r]\)在开头有M的情况下,区间内有\((1)\)或没有\((0)\)M的情况下的最短串
如果\([l,r]\)区间呈现\(AA\)形式,就可以令
\[f[l][r][0] = f[l][mid][0] + 1\]
然后枚举区间断点:
\[f[l][r][0] = min(f[l][k][0] + r - k)\]

对于\(1\)的转移,我们枚举中间的M
\[f[l][r][1] = min(min(f[l][k][1],f[l][k][0]) + 1 + min(f[k + 1][r][1],f[k+ 1][r][0]))\]

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
using namespace std;
const int maxn = 55,maxm = 100005,INF = 1000000000;
int f[maxn][maxn][2],n;
char s[maxn];
bool check(int l,int r){
    if ((r - l + 1) & 1) return false;
    int mid = l + ((r - l + 1) >> 1) - 1;
    for (int i = 0; l + i <= mid; i++) if (s[l + i] != s[mid + 1 + i])
        return false;
    return true;
}
int main(){
    scanf("%s",s + 1); n = strlen(s + 1);
    fill(f[0][0],f[0][0] + 2 * maxn * maxn,INF);
    for (int i = 1; i <= n; i++) f[i][i][0] = 1;
    for (int len = 2; len <= n; len++){
        for (int i = 1; i + len - 1 <= n; i++){
            int j = i + len - 1;
            if (check(i,j)) f[i][j][0] = f[i][i + ((j - i + 1) >> 1) - 1][0] + 1;
            for (int k = i; k < j; k++)
                f[i][j][0] = min(f[i][j][0],f[i][k][0] + j - k);
            for (int k = i; k < j; k++)
                f[i][j][1] = min(f[i][j][1],min(f[i][k][1],f[i][k][0]) + 1 + min(f[k + 1][j][0],f[k + 1][j][1]));
        }
    }
    printf("%d\n",min(f[1][n][0],f[1][n][1]));
    return 0;
}

转载于:https://www.cnblogs.com/Mychael/p/8890158.html

发布了0 篇原创文章 · 获赞 9 · 访问量 5万+
展开阅读全文
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览