zoukankan      html  css  js  c++  java
  • [区间DP]JZOJ 3095 秘密文件

    Description

    某天,情报局得到了一份秘密文件。文件的内容是加密后的全部由大写字母组成字符串。情报局局长小明想将其发送给远在东方神秘的XX大陆上的老朋友小刘来解密。然而若字符串太长,则需要很长的发送时间,太不安全了,因此小明想尽量将其缩短。于是小明制定了这样一个缩短规则:若一个字符串t连续出现k次,则可以用k(t)进行说明。如ABABAB可以缩成3(AB)。当然,重复缩短是允许的,如ABABABAAAAAAABABABAAAAAA可以缩成2(3(AB)6(A))


    现在,小明想知道,对于给定的字符串,最短可以缩成什么样子。


     

    Input

    输入仅一行,为给定的字符串。


    Output

    输出仅一行,为经过缩短操作后的字符串。


    若有多解,输出任意解即可。


     

    Sample Input

    AAAAAAAAAABABABCCD

    Sample Output

    9(A)3(AB)CCD
     

    Data Constraint

     
     

    Hint

    对于100%的数据,字符串的长度L<=100。

    分析

    本来想贪心的,后面发现数字长度也可能出锅

     那就DP

    DP方程挺简单的: 

    f[l][r]表示l~r缩减的最小长度

    c[l][r]表示l~r缩减最小长度的串

    k是区间内任意一点(分治点)

    len是区间内重复子串的长度

    DP方程显然f[l][r]=min{f[l][k]+f[k+1][r],f[l][l+len-1]+重复次数的位数+2

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int N=110;
    int f[N][N];
    string c[N][N],s;
    
    bool Judge(int l,int r,int length) {
        if ((r-l+1)%length) return 0;
        for (int i=1;i<=r-l+1;i++)
            if (s[l+i-1]!=s[l+(i-1)%length]) return 0;
        return 1;
    }
    
    int Digit(int num) {
        int ans=0;
        while (num) {
            ans++;
            num/=10;
        }
        return ans;
    }
    
    string Change(int num) {
        string s="";
        while (num) {
            s+=(num%10+48);
            num/=10;
        }
        for (int i=0;i<s.length()/2;i++) {
            char c=s[i];
            s[i]=s[s.length()-i-1];
            s[s.length()-i-1]=c;
        }
        return s;
    }
    
    void Solve(int l,int r) {
        if (f[l][r]) return;
        if (l==r) {
            f[l][r]=1;
            c[l][r]+=s[l];
            return;
        }
        f[l][r]=r-l+1;
        for (int i=l;i<=r;i++) c[l][r]+=s[i];
        for (int i=l;i<r;i++) {
            Solve(l,i);Solve(i+1,r);
            if (f[l][r]>f[l][i]+f[i+1][r]) {
                f[l][r]=f[l][i]+f[i+1][r];
                c[l][r]=c[l][i]+c[i+1][r];
            }
        }
        for (int i=1;i<=r-l;i++)
            if (Judge(l,r,i)) {
                Solve(l,l+i-1);
                if (f[l][r]>f[l][l+i-1]+2+Digit((r-l+1)/i)) {
                    f[l][r]=f[l][l+i-1]+2+Digit((r-l+1)/i);
                    c[l][r]=Change((r-l+1)/i)+"("+c[l][l+i-1]+")";
                }
            }
    }
    
    int main() {
        cin>>s;
        Solve(0,s.length()-1);
        cout<<c[0][s.length()-1];
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    Weather with you主题说明
    搜索枚举
    洛谷P2085——最小函数值
    洛谷P1402——乒乓球
    CSP2019,RP+=150。
    搜索之连通块(深搜广搜版)
    appium
    appium环境搭建
    Python抓取淘宝IP地址数据
    记录日志
  • 原文地址:https://www.cnblogs.com/mastervan/p/9867358.html
Copyright © 2011-2022 走看看