LA 3363 String Compression 区间dp

LA 3363

题意:输入一个字符串,字符串如果有相同的子串,你可以进行压缩,如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)));
	}
}

猜你喜欢

转载自blog.csdn.net/ccsu_cat/article/details/80272786