题意:
给出一个字符串,然后要你把他折叠成一个最短的字符串
例如
AAAAAAAAAABABABCCD
NEERCYESYESYESNEERCYESYESYES
变成:
9(A)3(AB)CCD
2(NEERC3(YES)
题解:
很容易看出来用分治的办法,但是不会把折叠起来,然后参考了一下别人的代码
这里主要是很巧妙的利用了string类,方便折叠与保存,以及sprintf函数,可以将数字转化为字符串(当然我们也可以自己手写合并字符串)
下面zip函数是求循环节函数
deal函数中if(len)后面是压缩字符串
#include<string>
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
char str[110];
int dp[110][110];
string fold[110][110];
int zip(int L,int R)
{
for(int i=1;i<=(R-L+1)/2;i++){
if((R-L+1)%i) continue;
bool flag=true;
for(int j=L;j+i<=R;j++)
if(str[j]!=str[j+i]){flag=false;break;}
if(flag) return i;
}
return 0;
}
int deal(int L,int R)
{
if(dp[L][R]!=-1) return dp[L][R];
if(L==R){dp[L][R]=1;fold[L][R]=str[L];return 1;}
int ret=INF,k,temp;
for(int i=L;i<R;i++){
temp=deal(L,i)+deal(i+1,R);
if(temp<ret){k=i,ret=temp;}
}
fold[L][R]=fold[L][k]+fold[k+1][R];
int len=zip(L,R);
if(len){
char t[10];
sprintf(t,"%d",(R-L+1)/len);
string nstr=t+string("(")+fold[L][L+len-1]+string(")");
if(nstr.size()<ret){ret=nstr.size();fold[L][R]=nstr;}
}
return dp[L][R]=ret;
}
int main()
{
freopen("in.txt","r",stdin);
while(scanf("%s",str)!=EOF)
{
memset(dp,-1,sizeof(dp));
int len=strlen(str);
deal(0,len-1);
cout<<fold[0][len-1]<<endl;
}
return 0;
}