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 }
  • 相关阅读:
    Android关机流程源码分析
    开关机画面
    android camera
    深入分析AIDL原理
    VMware 虚拟机里连不上网的三种解决方案
    查看Linux中自带的jdk ,设置JAVA_HOME
    Hadoop三种模式安装教程(详解)
    Java ArrayList遍历删除问题
    idea git的使用(四)git建立分支与合并分支
    SpringBoot非官方教程 | 终章:文章汇总
  • 原文地址:https://www.cnblogs.com/wyboooo/p/9779264.html
Copyright © 2011-2022 走看看