zoukankan      html  css  js  c++  java
  • poj2176 Folding【区间DP】

    Folding
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 1841   Accepted: 642   Special Judge

    Description

    Bill is trying to compactly represent sequences of capital alphabetic characters from 'A' to 'Z' by folding repeating subsequences inside them. For example, one way to represent a sequence AAAAAAAAAABABABCCD is 10(A)2(BA)B2(C)D. He formally defines folded sequences of characters along with the unfolding transformation for them in the following way: 
    • A sequence that contains a single character from 'A' to 'Z' is considered to be a folded sequence. Unfolding of this sequence produces the same sequence of a single character itself. 
    • If S and Q are folded sequences, then SQ is also a folded sequence. If S unfolds to S' and Q unfolds to Q', then SQ unfolds to S'Q'. 
    • If S is a folded sequence, then X(S) is also a folded sequence, where X is a decimal representation of an integer number greater than 1. If S unfolds to S', then X(S) unfolds to S' repeated X times.

    According to this definition it is easy to unfold any given folded sequence. However, Bill is much more interested in the reverse transformation. He wants to fold the given sequence in such a way that the resulting folded sequence contains the least possible number of characters. 

    Input

    The input contains a single line of characters from 'A' to 'Z' with at least 1 and at most 100 characters.

    Output

    Write to the output a single line that contains the shortest possible folded sequence that unfolds to the sequence that is given in the input file. If there are many such sequences then write any one of them.

    Sample Input

    AAAAAAAAAABABABCCD
    

    Sample Output

    9(A)3(AB)CCD
    

    Source

    题意:

    给一个字符串,尽量压缩,让他长度最短。()和数字都是算长度的。所以样例里CC才没有变成2(C)

    思路:

    能够想到的是子结构是保存区间i,j中最短的串的长度len,以及这个最短的串

    状态转移的时候我们有两种操作,一种就是简单的找一个中间的点,把两边的串合并。这个比较简单。

    一种是看这个串能如何压缩。于是我们可以去枚举最后压缩了之后的子串的长度,不包括数字和括号。

    对于一个区间(i, j)我们从小到大枚举压缩后的子串长度,因为压缩的越小越好。压缩完成后去比较是压缩比较好还是合并比较好。

    每一次枚举区间长度和起始点。

     1 //#include <bits/stdc++.h>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<stdio.h>
     6 #include<cstring>
     7 #include<vector>
     8 #include<map>
     9 #include<set>
    10 
    11 #define inf 0x3f3f3f3f
    12 using namespace std;
    13 typedef long long LL;
    14 
    15 struct seg{
    16     int len;
    17     char str[110];
    18 }dp[110][110];
    19 char s[110];
    20 int n;
    21 
    22 int main(){
    23 
    24     while(scanf("%s", s + 1) != EOF){
    25         n = strlen(s + 1);
    26         for(int i = 1; i <= n; i++){
    27             dp[i][i].len = 1;
    28             dp[i][i].str[0] = s[i];
    29         }
    30 
    31         for(int l = 2; l <= n; l++){
    32             for(int i = 1; i <= n - l + 1; i++){
    33                 int j = i + l - 1;
    34                 dp[i][j].len = inf;
    35                 for(int nowl = 1; nowl <= l / 2; nowl++){//枚举子串压缩后的长度
    36                     if(l % nowl)continue;
    37                     int st = i, ed = i + nowl;
    38                     while(s[st] == s[ed] && ed <= j)st++, ed++;
    39                     if(ed > j){
    40                         int num = l / nowl;
    41                         sprintf(dp[i][j].str, "%d", num);
    42                         strcat(dp[i][j].str, "(");
    43                         strcat(dp[i][j].str, dp[i][i + nowl - 1].str);
    44                         strcat(dp[i][j].str, ")");
    45                         dp[i][j].len = strlen(dp[i][j].str);
    46                         break;
    47                     }
    48                 }
    49                 for(int k = i; k < j; k++){
    50                     if(dp[i][j].len > dp[i][k].len + dp[k + 1][j].len){
    51                         dp[i][j].len = dp[i][k].len + dp[k + 1][j].len;
    52                         strcpy(dp[i][j].str, dp[i][k].str);
    53                         strcat(dp[i][j].str, dp[k + 1][j].str);
    54                     }
    55                 }
    56             }
    57         }
    58         
    59         printf("%s
    ", dp[1][n].str);
    60     }
    61     return 0;
    62 }
  • 相关阅读:
    根据用户输入的时间查询那天的数据
    动软 生成 linq相关DAO
    pdf 移除密码 去除水印 批量去除水印 编辑文字 批量替换文字
    利用OCR识别扫描的jpg、tif文件的文字
    jstat命令详解
    IDEA自动编译设置
    IntelliJ IDEA:Field injection is not recommended
    阿里巴巴Druid数据库连接池配置详解及使用
    com.mysql.jdbc.Driver和com.mysql.cj.jdbc.Driver的区别
    Java对元与分的金额的转换
  • 原文地址:https://www.cnblogs.com/wyboooo/p/9779264.html
Copyright © 2011-2022 走看看