题意:输入一个字符串,字符串如果有相同的子串,你可以进行压缩,如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的子串重复组成的数字长度,(数字9的长度为1,数字10的长度为2),2表示括号()的长度。
#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))); } }