Folding

本文深入探讨了一种字符串压缩算法,旨在寻找将给定序列转换为最短收缩序列的方法,通过区间递推和循环节优化,实现了高效解压。文章提供了详细的算法思路与三种实现方式,包括string阶段实现、dfs实现及char数组实现。

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

Code folding allows users to collapse and expand sections of code, which is useful for managing large code files. ### Usage - **Keyboard Shortcuts**: In many integrated development environments (IDEs) and text editors, there are specific keyboard shortcuts for code folding. For example, in Visual Studio Code, you can use `Ctrl + Shift + [` to fold a code block and `Ctrl + Shift + ]` to unfold it. - **Menu Options**: Most editors also provide menu options for code folding. You can usually find these under the "View" or "Edit" menu. ### Supported Tools - **Visual Studio Code**: It has a powerful code folding feature that supports various programming languages. You can fold functions, classes, blocks of code, and more. For example, in a JavaScript file, you can fold function definitions to get a high - level view of the code. ```javascript function exampleFunction() { // Code inside the function let variable = 10; return variable; } ``` - **IntelliJ IDEA**: This IDE provides extensive code folding capabilities. It can fold imports, methods, loops, and other code constructs. For Java code, you can easily fold a large `try - catch` block. ```java try { // Some code that might throw an exception int result = 10 / 0; } catch (ArithmeticException e) { // Handle the exception e.printStackTrace(); } ``` - **Sublime Text**: Sublime Text also offers code folding functionality. You can fold code regions based on indentation or specific syntax constructs. For a Python file, you can fold entire function bodies. ```python def another_function(): # Code inside the Python function value = 20 return value ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值