Folding

Folding

给出一个长度为n的序列\(\{a_i\}\),定义一个收缩的序列变为原序列的方式为

  1. 如果该收缩序列只有一个字符,原序列即该个字符。
  2. 如果一个收缩序列由多个收缩序列,那么分别对各个收缩序列进行解压,即原序列
  3. 如果收缩序列形如\(n(S)\),意为收缩序列S重复n次(注意,n为数字,转化成字符需要占空间),解压即把该序列重复n次。

请找到一个最短的收缩序列,解压后正好为序列\(\{a_i\}\),\(n\leq 100\)。

显然问题具有区间划分性,因为几个收缩序列可以组成一个收缩序列,于是可以考虑区间递推,设\(f[i][j]\)表示合并\([i,j]\)后的最短的字符串,(接下来的+为字符串的相加,比较大小为字符串长度的比较,不知道意思查string的用法),首先区间合并性可以

\[f[i][j]=\min_{k=i}^{j-1}\{f[i][k]+f[k+1][j]\}\]

现在来考虑循环节的问题,循环节可以\(O(n^2)\)枚举,但是所有的循环节中必然是最短的循环节最优(感性理解一下),设最短循环节为k,有

\[f[i][j]=\min(f[i][j],to\_string(k)+"("+f[i][k-1]+")")\]

边界:\(f[i][i]=a_i\)

答案:\(f[1][n]\)

参考代码:

string 阶段实现

#include <iostream>
#include <cstdio>
#define il inline
#define ri register
using namespace std;
string s,dp[101][101],lsy;
il string To(int);
il int xh(int,int);
int main(){
    cin>>s;
    for(int i(1);i<=s.size();++i)
        dp[i][i].push_back(s[i-1]);
    for(int i,j(1),k;j<=s.size();++j)
        for(i=j-1;i;--i){
            for(k=i;k<j;++k){
                lsy=dp[i][k]+dp[k+1][j];
                if(!dp[i][j].size()||dp[i][j].size()>lsy.size())
                    dp[i][j]=lsy;
            }k=xh(i,j);
            if(k){
                lsy=To((j-i+1)/k)+"("+dp[i][i+k-1]+")";
                if(lsy.size()<dp[i][j].size())
                    dp[i][j]=lsy;
            }
        }cout<<dp[1][s.size()].size();
    return 0;
}
il string To(int x){
    string ans;int w(1);while(w<=x)w*=10;w/=10;
    while(w)ans.push_back(x/w+48),x%=w,w/=10;
    return ans;
}
il int xh(int l,int r){
    int len(r-l+1);
    for(int i(1),j;i<=(len>>1);++i){
        if(len%i)continue;
        for(j=l;j<=r-i;++j){
            if(s[j-1]==s[j+i-1])continue;
            break;
        }if(j>r-i)return i;
    }return 0;
}

string dfs实现

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#define il inline
#define ri register
using namespace std;
string s,dp[101][101],
    dfs(int,int);
il int cycle(int,int);
il string To_string(int);
int main(){
    cin>>s;
    for(int i(1);i<=s.size();++i)
        dp[i][i].push_back(s[i-1]);
    cout<<dfs(1,s.size())<<endl;
    return 0;
}
il string To_string(int x){
    string ans;int w(1);
    while(w<=x)w*=10;w/=10;
    while(w)ans.push_back(x/w+48),
                x%=w,w/=10;return ans;
}
il int cycle(int l,int r){
    int len(r-l+1);
    for(int i(1),j;i<=(len>>1);++i){
        if(len%i)continue;
        for(j=l;j<=r-i;++j){
            if(s[j-1]==s[j+i-1])continue;
            break;
        }if(j>r-i)return i;
    }return 0;
}
string dfs(int l,int r){
    if(dp[l][r].size())return dp[l][r];
    string lsy;
    for(int k(l);k<r;++k){
        lsy=dfs(l,k)+dfs(k+1,r);
        if(lsy.size()<dp[l][r].size()
           ||!dp[l][r].size())dp[l][r]=lsy;
    }int k(cycle(l,r));
    if(k){
        lsy=dfs(l,l+k-1);
        lsy=To_string((r-l+1)/k)+"("+lsy+")";
        if(lsy.size()<dp[l][r].size())dp[l][r]=lsy;
    }return dp[l][r];
}

char数组实现

#include <iostream>
#include <cstdio>
#include <cstring>
#define il inline
#define ri register
#define intmax 0x7fffffff
using namespace std;
struct String{
    char s[111];int len;
    il void read(){
        scanf("%s",s);
        len=strlen(s);
    }
}s,dp[101][101],lsy;
il int xh(int,int);
int main(){
    s.read();
    for(int i(1);i<=s.len;++i)
        dp[i][i].s[0]=s.s[i-1],
            dp[i][i].len=1;
    for(int i,j(1),k,l;j<=s.len;++j)
        for(i=j-1;i;--i){
            dp[i][j].len=intmax;
            for(k=i;k<j;++k)
                if(dp[i][k].len+dp[k+1][j].len<dp[i][j].len)
                    dp[i][j].len=dp[i][k].len+dp[k+1][j].len,l=k;
            strcpy(dp[i][j].s,dp[i][l].s);
            strcat(dp[i][j].s,dp[l+1][j].s);
            l=xh(i,j);if(l){
                sprintf(lsy.s,"%d",(j-i+1)/l),strcat(lsy.s,"(");
                strcat(lsy.s,dp[i][i+l-1].s),strcat(lsy.s,")");
                lsy.len=strlen(lsy.s);
                if(lsy.len<=dp[i][j].len)
                    dp[i][j]=lsy;
            }
        }printf("%s",dp[1][s.len].s);
    return 0;
}
il int xh(int l,int r){
    int L(r-l+1);
    for(int i(1),j;i<=(L>>1);++i){
        if(L%i)continue;
        for(j=l;j<=r-i;++j){
            if(s.s[j-1]==s.s[j+i-1])continue;
            break;
        }if(j>r-i)return i;
    }return 0;
}

原文地址:https://www.cnblogs.com/a1b3c7d9/p/11001525.html

时间: 2024-10-31 13:29:32

Folding的相关文章

UVA1630 Folding 区间DP

Folding 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

【转】Scala片段 1:Folding

原文链接  http://www.ituring.com.cn/article/131425 本文翻译自: Scala snippets 1: Folding 个人能力有限 如翻译不恰当的地方麻烦指正下^_^ [email protected] Scala为Java开发者提供了很多不错的特性和类库以此来编写更优美和简洁的代码. 但一下子要理解这么多的概念是一件困难的事.在这个由短小的文章组成的系列中, 我将会示范一些scala背后的观点,并且向你展示如何使用它们. 这个系列没有严格的结构,我只是

Codeforces Round #397 by Kaspersky Lab and Barcelona Bootcamp (Div. 1 + Div. 2 combined) E. Tree Folding

地址:http://codeforces.com/contest/765/problem/E 题目: E. Tree Folding time limit per test 2 seconds memory limit per test 512 megabytes input standard input output standard output Vanya wants to minimize a tree. He can perform the following operation mu

Eclipse折叠代码 coffee bytes code folding

提供一个插件下载地址,博客园的: http://files.cnblogs.com/wucg/com.cb.eclipse.folding_1.0.6.jar.zip http://files.cnblogs.com/wucg/eclipse-folding-plugin.zip http://stackoverflow.com/questions/6940199/how-to-use-coffee-bytes-code-folding 首先,您需要配置Coffee Bytes Java fol

6.8.1 映射、筛选和折叠(Mapping, filtering, and folding)

6.8.1 映射.筛选和折叠(Mapping,filtering, and folding) 映射.筛选和折叠是函数编程中最常见的操作:在处理函数式列表时,我们已经用到过,但它们还支持所有其他的集合类型(我们将在第十和十二章讨论其中一部分):这些操作并不限于集合,所有的操作都可用于处理选项类型. 清单 6.25 显示了映射.筛选和折叠函数的签名类型,清单中包括了我们尚未讨论过的Option.filter 和 Option.fold 函数. 清单6.25 map.filter 和 fold 函数签

化学键|甘氨酸|谷氨酸|半胱胺酸|motif|domain|疏水相互作用|序列相似性|clustering analysis|Chou and Fasman|GOR|PHD|穿线法|first-principle ab initio folding|

生命组学 对Protein的分析可以从Sequence到structure到function,最后研究interaction. Structure: 化学键形成骨架,化学元素的选取基于合成蛋白质选择容易获取的元素,氨基酸化学元素的选取决定了其结构,其结构又决定了function.氨基酸的组织结构可以解释其function:甘氨酸最小,所以可以放到不同位置:谷氨酸顺反式都有,所以便于结构调整:半胱胺酸因有二硫键而连接紧密. 蛋白质有four levels:一级结构由共价键连接,sequence与结

uva 177:Paper Folding(模拟 Grade D)

题目链接 题意:一张纸,每次从右往左对折.折好以后打开,让每个折痕都自然的呈90度.输出形状. 思路:模拟折……每次折想象成把一张纸分成了正面在下的一张和反面在上的一张.维护左边和方向,然后输出.细节有点多. 代码: #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> using namespace std; #define N (1<<13)+

UVA - 1630 Folding(串折叠)(dp---记忆化搜索)

题意:给出一个由大写字母组成的长度为n(1<=n<=100)的串,"折叠"成一个尽量短的串.折叠可以嵌套.多解时可输出任意解. 分析: 1.dp[l][r]为l~r区间可折叠成的最短串的长度. 2.ans[l][r]为l~r区间可折叠成的最短串. 3.先判断当前研究的串是否能折叠,若不能折叠,再枚举分割线,折叠分隔后可折叠的串,以使处理后的串最短. #pragma comment(linker, "/STACK:102400000, 102400000"

Codeforces 765E. Tree Folding [dfs][树形dp]

题解:先从节点1开始dfs.对于每一个节点,用一个set记录:以该点为根的子树的深度. a) 如果此节点的某个子节点打出了GG,则此节点直接打出GG. b) 若set的元素个数<=1,那么,以该点为根的子树,显然是可以缩成一条链滴!且该点为链的端点.c) 若set元素个数=2,以该点为根的子树,也可以收缩成一条链,且该点不是链的端点.此时,我们继续分类讨论. i) 该点没有父亲.我们成功找到了一条链~岂不美哉. ii) 该点有父亲,那么在链上会长出一根奇怪的东西.那我们赶紧报警,把该点赋给roo