题意:输入一个字符串,字符串如果有相同的子串,你可以进行压缩,如gogogo-->3(go),压缩后字符串的长度就变成了5,letsgogogoletsgogogo-->2(lets3(go)),压缩后该字符串的长度就变成了12,让你求输入字符串压缩后最短长度。
思路:设d[i][j]为子串[i,j]的最短长度,那么明显d[i][j]=min(d[ i ][ k ]+d[k+1][ j ],count(k)+2+d[ i ][ k ]),count(k)表示串[ i, j ]有几个串[ i, k ]。
#include<stdio.h>
#include<string.h>
#define min(x,y) x<y?x:y
char s[205];
int vis[205][205];
int d[205][205];
int count(int k,int i,int j)
{
if((j-i+1)%(k-i+1))
return 0;
for(int p=k+1;p<=j;p++)
if(s[p]!=s[p-k-1+i])
return 0;
int t=(j-i+1)/(k-i+1);
int sum=0;
while(t)
{
sum++;
t/=10;
}
return sum;
}
int dfs(int i,int j)
{
if(vis[i][j])
return d[i][j];
vis[i][j]=1;
d[i][j]=j-i+1;
for(int k=i;k<j;k++)
{
d[i][j]=min(d[i][j],dfs(i,k)+dfs(k+1,j));
int t=count(k,i,j);
if(t)
d[i][j]=min(d[i][j],t+2+dfs(i,k));
}
return d[i][j];
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",s+1);
memset(vis,0,sizeof(vis));
printf("%d\n",dfs(1,strlen(s+1)));
}
}