1090: [SCOI2003]字符串折叠

题目链接

题目大意:折叠的定义如下: 1. 一个字符串可以看成它自身的折叠。2. X(S)是X(X>1)个S连接在一起的串的折叠,记作X(S) 3. 折叠可以嵌套。给一个字符串,求它的最短折叠。

题解:区间dp
f[l][r] 表示 [l,r] 压缩后最短长度,初始值 f[l][r]=rl+1
转移:枚举区间分割点 k,lk<r
(1)不折叠: f[l][r]=f[l][k]+f[k+1][r]
(2)折叠: f[l][r]=f[l][k]+2+calc((rl+1)/(kl+1)) ,要求k+1~r可以由l~k重复得到,其中2为括号长度,calc为总长度/循环节长度即系数所占长度

答案即为 f[1][n]

我的收获:区……间dp

#include <iostream>  
#include <cmath>  
#include <cstdio>  
#include <cstring>  
#include <algorithm>  
using namespace std;

const int M=105;

char s[M];  
int bit,f[M][M];

bool lyd(int l1,int r1,int l2,int r2)//
{  
    if((r1-l1+1)%(r2-l2+1)!=0) return 0;  
    for(int i=l1;i<=r1;i++)  
        if(s[i]!=s[(i-l1)%(r2-l2+1)+l2]) return 0;  
    return 1;  
}  

int get(int x)//求位数 
{  
    for(bit=0;x;x/=10,bit++);
    return bit;
}

int DP(int l,int r)  
{  
    if(l==r) return 1;  
    if(f[l][r]!=-1) return f[l][r]; 
    int now=r-l+1;
    for(int k=l;k<r;k++)  
    {
        now=min(now,DP(l,k)+DP(k+1,r));//(1)不折叠 
        if(lyd(k+1,r,l,k)) now=min(now,DP(l,k)+2+get((r-l+1)/(k-l+1)));//(2)折叠 
    }
    return f[l][r]=now;
}   

void work(){
    scanf("%s",s+1);
    memset(f,-1,sizeof(f));
    printf("%d\n",DP(1,strlen(s+1)));
}

int main()  
{  
    work(); 
    return 0;  
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值