您的位置:首页 > 其它

【BZOJ 1090】[SCOI2003]字符串折叠

2016-02-25 08:26 357 查看

Description

折 叠的定义如下: 1. 一个字符串可以看成它自身的折叠。记作S  S 2. X(S)是X(X>1)个S连接在一起的串的折叠。记作X(S)  SSSS…S(X个S)。 3. 如果A  A’, BB’,则AB  A’B’ 例如,因为3(A) = AAA, 2(B) = BB,所以3(A)C2(B)  AAACBB,而2(3(A)C)2(B)AAACAAACBB 给一个字符串,求它的最短折叠。例如AAAAAAAAAABABABCCD的最短折叠为:9(A)3(AB)CCD。

Input

仅一行,即字符串S,长度保证不超过100。

Output

仅一行,即最短的折叠长度。

Sample Input

NEERCYESYESYESNEERCYESYESYES

Sample Output

14

HINT

一个最短的折叠为:2(NEERC3(YES))

又是区间型DP,然后又没推出方程,果真我的DP不是一般的弱啊,hhh

f[i][j]表示最短长度

f[i][j]=min(f[i][k]+f[k+1][j])//不解释

f[i][j]=min(f[i][k]+cal((j-k)/(k-i+1)+1)) //若j-k是k-i+1的n倍。。。

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int f[110][110];
char s[110];
bool judge(int l,int r,int ll,int rr){
if((r-l+1)%(rr-ll+1)) return 0;
for(int i=l;i<=r;i++) if(s[i]!=s[(i-l)%(rr-ll+1)+ll]) return 0;
return 1;
}

int calc(int x){
int t=0;
while(x){
t++; x/=10;
}
return t;
}

int dp(int l,int r){
if(l==r) return 1;
if(f[l][r]!=-1) return f[l][r];
int tmp=(r-l+1);
for(int i=l;i<r;i++) tmp=min(tmp,dp(l,i)+dp(i+1,r));
for(int i=l;i<r;i++)
if(judge(i+1,r,l,i))
tmp=min(tmp,dp(l,i)+2+calc((r-i)/(i-l+1)+1));
f[l][r]=tmp;
return tmp;
}

int main(){
scanf("%s",s+1);
int len=strlen(s+1);
memset(f,-1,sizeof(f));
printf("%d",dp(1,len));
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: