题意: 将字符串压缩到最短。压缩规则见题目。
分析: 这题我就是用了最原始的方法了。一段一段来压缩。即现在要压缩[i,j]这一段时,要保证任意一段长度比j-i+1小的压缩结果都已经得出来了,也就是按长度从小到大来dp。压缩[i,j]的方法有两种,一种压缩成"数字(字符串)"的形式,另一种是压缩成[i,k][k+1,j]的形式。比较一下,哪种短就选哪种了。
#include <iostream>
#include <stdio.h>
#include <memory.h>
using namespace std;
#define inf 200000000
struct node
{
int len;
char ss[110];
}f[110][110];
char ts[110];
int pos;
void tostring(int num)
{
char cc;
int i;
pos=-1;
while(num)
{
ts[++pos]=(num%10)+'0';
num/=10;
}
for(i=0;i<=pos/2;i++)
{
cc=ts[i]; ts[i]=ts[pos-i]; ts[pos-i]=cc;
}
}
int main()
{
int i,j,k,nlen,now,p,q,n,num;
char s[110];
while(scanf("%s",s+1)!=EOF)
{
n=strlen(s+1);
for(i=1;i<=n;i++) // 初始化
{
f[i][i].ss[0]=s[i];
f[i][i].ss[1]='\0';
f[i][i].len=1;
}
for(nlen=2;nlen<=n;nlen++) // 现在的长度
{
for(i=1;i+nlen-1<=n;i++)
{
j=i+nlen-1;
f[i][j].len=inf;
// 先看能不能压缩成"数字(字符串)"的形式
for(now=1;now<nlen;now++) // now---想折叠成的长度
{
if(nlen%now) continue;
q=i+now; p=i;
while(q<=j)
{
if(s[q]!=s[p]) break;
p++; q++;
if(p==i+now) p=i;
}
if(q>j) // 可以压缩成"数字(字符串)"的形式
{
num=nlen/now;
tostring(num);
strcpy(f[i][j].ss,ts);
f[i][j].ss[++pos]='(';
for(p=0;f[i][i+now-1].ss[p];p++) f[i][j].ss[++pos]=f[i][i+now-1].ss[p];
f[i][j].ss[++pos]=')';
f[i][j].len=pos+1;
f[i][j].ss[++pos]='\0';
break;
}
}
for(k=i;k<j;k++) // [i,k][k+1,j]这种形式
{
if(f[i][k].len+f[k+1][j].len<f[i][j].len)
{
f[i][j].len=f[i][k].len+f[k+1][j].len;
strcpy(f[i][j].ss,f[i][k].ss);
strcat(f[i][j].ss,f[k+1][j].ss);
}
}
}
}
printf("%s\n",f[1][n].ss);
}
return 0;
}