【JZOJ B组】秘密文件

97 篇文章 0 订阅
4 篇文章 0 订阅

Description

某天,情报局得到了一份秘密文件。文件的内容是加密后的全部由大写字母组成字符串。情报局局长小明想将其发送给远在东方神秘的XX大陆上的老朋友小刘来解密。然而若字符串太长,则需要很长的发送时间,太不安全了,因此小明想尽量将其缩短。于是小明制定了这样一个缩短规则:若一个字符串t连续出现k次,则可以用k(t)进行说明。如ABABAB可以缩成3(AB)。当然,重复缩短是允许的,如ABABABAAAAAAABABABAAAAAA可以缩成2(3(AB)6(A))

现在,小明想知道,对于给定的字符串,最短可以缩成什么样子。

Input

输入仅一行,为给定的字符串。

Output

输出仅一行,为经过缩短操作后的字符串。

若有多解,输出任意解即可。

Sample Input

AAAAAAAAAABABABCCD

Sample Output

9(A)3(AB)CCD

Hint

对于100%的数据,字符串的长度L<=100。

思路

区间DP

设f[i][j]为区间i–j的最小长度
则可以枚举断点k,用f[i][k]+f[k+1][j]来更新
如果区间i–j是由多段重复的子串构成,则可以更新答案

代码

#include <cstdio>
#include <iostream>
#include <cstring>
#define N 110
using namespace std;
int len;
string f[N][N],s;
bool check(int l,int r,int L,int R)
{
	if((r-l+1)%(R-L+1)) return 0;
	for(int i=l; i<=r; i++) if(s[i]!=s[(i-l)%(R-L+1)+L]) return 0;
	return 1;
}
string change(int x)
{
	string t; 
	for(; x; x/=10) t=char(x%10+'0')+t;
	return t;
}
string dfs(int l,int r)
{
	if(l==r) return s.substr(l,1);
	if(f[l][r].length()>0) return f[l][r];
    f[l][r]=s.substr(l,r-l+1);
	for(int i=l; i<r; i++)
		if(f[l][r].length()>dfs(l,i).length()+dfs(i+1,r).length()) 
			f[l][r]=dfs(l,i)+dfs(i+1,r);
	for(int i=l; i<r; i++)	
		if(check(l,i,i+1,r))
		{	
			string str=change((r-l+1)/(r-i))+"("+dfs(i+1,r)+")";
			if(f[l][r].length()>str.length()) f[l][r]=str;
		}
	return f[l][r];
}
int main()
{
	cin>>s;
	len=s.length();
	cout<<dfs(0,len-1);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值