BZOJ1090[SCOI2003] 字符串折叠

原题链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1090

字符串折叠

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))

题解

d p [ l ] [ r ] dp[l][r] dp[l][r]表示区间 [ l , r ] [l,r] [l,r]的最短长度,转移的时候需要枚举分界点合并,同时看一下中间的串能否合并为一个串。

代码
#include<bits/stdc++.h>
using namespace std;
const int M=105;
char ch[M];
int dp[M][M];
bool merge(int l1,int r1,int l2,int r2)
{
	if((r1-l1+1)%(r2-l2+1))return 0;
	for(int i=l1;i<=r1;++i)if(ch[i]!=ch[(i-l1)%(r2-l2+1)+l2])return 0;
	return 1;
}
int lg(int x){int t=0;while(x){x/=10;t++;}return t;}
int dfs(int l,int r)
{
	if(l==r)return 1;
	if(dp[l][r])return dp[l][r];
	int ans=r-l+1;
	for(int i=l;i<r;++i)
	{
		ans=min(ans,dfs(l,i)+dfs(i+1,r));
		if(merge(i+1,r,l,i))ans=min(ans,dfs(l,i)+2+lg((r-i)/(i-l+1)+1));
	}
	return dp[l][r]=ans;
}
void in(){scanf("%s",ch+1);}
void ac(){printf("%d",dfs(1,strlen(ch+1)));}
int main(){in(),ac();}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值