字符串压缩
题目描述
我们有如下几个定义:
• 只包含单个大写英文字母的序列
A
是压缩序列。
• 如果序列
A
和
• 如果
S
是压缩序列,那么
给定一个序列
输入格式
一个长为 n 的字符串。
输出格式
输出序列
样例输入
AAAAAAAAAABABABCCD
样例输出
9(A)3(AB)CCD
数据范围
n≤100
Solution
用
f[i][j]
表示从
i
到
则
f[i][j]=max(f[i][k],f[k+1][j])
若 str[i][k] 翻若干倍可变成 str[i][j] ,则
f[i][j]=max(j−i+1,getlen((j−i+1)/(k−i+1))+2+f[i][k])
Code
#include <iostream>
#include <cstdio>
#include <cstring>
#define Min(x,y) ((x)<(y)?(x):(y))
using namespace std;
int f[110][110],g[110][110],Len[110],n;
bool h[110][110];
char str[110];
int get_len(int x){
if(Len[x])return Len[x];
if(!x)return 1;
int cnt=0;
while(x)cnt++,x/=10;
return cnt;
}
void work(int l,int r){
if(g[l][r]==-1){
char ch=str[r+1];
str[r+1]='\0';
printf("%s",str+l);
str[r+1]=ch;
}
else{
if(h[l][r]){
printf("%d(",(r-l+1)/(g[l][r]-l+1));
work(l,g[l][r]);
printf(")");
}
else{
work(l,g[l][r]);
work(g[l][r]+1,r);
}
}
}
bool done(int x,int y,int z){
int need=(z-x+1)/(y-x+1),lenth=(y-x+1);
for(int i=1;i<need;i++)
for(int j=x;j<=y;j++)
if(str[j+lenth*i]!=str[j])
return false;
return true;
}
int main(){
freopen("compress.in","r",stdin);
freopen("compress.out","w",stdout);
memset(f,0x3f,sizeof f);
scanf("%s",str+1);
n=strlen(str+1);
for(int i=1;i<=n;i++){
f[i][i]=1;
g[i][i]=-1;
}
for(int i=n;i>=1;i--)
for(int j=i+1;j<=n;j++){
f[i][j]=j-i+1;g[i][j]=-1;h[i][j]=false;
for(int k=i;k<j;k++){
if(f[i][j]>f[i][k]+f[k+1][j]){
f[i][j]=f[i][k]+f[k+1][j];
g[i][j]=k;h[i][j]=false;
}
f[i][j]=Min(f[i][j],f[i][k]+f[k+1][j]);
if((j-i+1)%(k-i+1)==0&&done(i,k,j)){
if(f[i][j]>get_len((j-i+1)/(k-i+1))+f[i][k]){
f[i][j]=get_len((j-i+1)/(k-i+1))+2+f[i][k];
g[i][j]=k;h[i][j]=true;
}
}
}
}
work(1,n);
return 0;
}