BZOJ 1068: [SCOI2007]压缩 区间dp

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

思路:这道题和1090很像,一开始做的时候直接压缩某段加M,恩恩还是太天真了,这样子处理的话M可能会交叉,
可能或出现多个M。
那么怎么处理呢。
思路如下:
dp{i,j,k}表示第i到第j这一段的最小长度。k表示该段是否含有M。
我们要分情况处理,首先呢,我们分成两段进行压缩,且默认两端都hasM为1,在两端中间加个M,
a....an M b....bn 这样子压缩的话我们就不要担心前一段会影响后一段了。
第二种情况,就是我们只压缩前面一段,后面一段不用压缩。t=Math.min(t,dp(l,i,hasM)+(r-i));
第三种情况,就是我们判断整一段,择半处理,如果前一段和后一段一样,那么我们就把后一段替换为R,
继续处理前一段即可,这一段是不存在M的。因为这样最后一定会压缩成xxxRRR的形式,M的话我们已经在之前就处理过了。
import java.io.InputStreamReader;
import java.util.Scanner;
public class __1068 {
    static boolean[][][] vis;
    static int[][][] f;
    static String s;

    static boolean repeat(int l,int r){
        int t=r-l+1;
        if((t&1)==1){
            return false;
        }
        for(int i=l;i<=(l+r)/2;++i){
            if(s.charAt(i)!=s.charAt(i+t/2)){
                return false;
            }
        }
        return true;
    }
    public static int dp(int l,int r,int hasM){
        if(l==r){
            return 1;
        }
        if(vis[l][r][hasM]){
            return f[l][r][hasM];
        }
        vis[l][r][hasM]=true;
        int t=r-l+1;
        if(hasM==1){
            for(int i=l;i<r;++i){
                t=Math.min(t,dp(l,i,1)+dp(i+1,r,1)+1);
            }
        }
        for(int i=l;i<r;++i){
            t=Math.min(t,dp(l,i,hasM)+(r-i));
        }
        if(repeat(l,r)){
            t=Math.min(t,dp(l,(l+r)/2,0)+1);
        }
        return f[l][r][hasM]=t;
    }

    public static void main(String[] args){
        Scanner cin=new Scanner(new InputStreamReader(System.in));
        s=cin.next();
        vis=new boolean[s.length()][s.length()][2];
        f=new int[s.length()][s.length()][2];
        System.out.println(dp(0,s.length()-1,1));
    }

}
发布了244 篇原创文章 · 获赞 69 · 访问量 13万+
展开阅读全文

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

©️2019 CSDN 皮肤主题: 游动-白 设计师: 上身试试

分享到微信朋友圈

×

扫一扫,手机浏览