码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 1090 SCOI2003 字符串折叠 动态规划+Hash

时间:2015-01-23 21:41:23      阅读:183      评论:0      收藏:0      [点我收藏+]

标签:bzoj   bzoj1090   动态规划   hash   

题目大意:给定一个字符串,求按照题中所给的压缩方式最短能压缩到多长

区间DP 令f[i][j]表示[i,j]区间内的字符串最短能压缩到多长

普通的区间DP:f[i][j]=min{f[i][k]+f[k+1][j]} (i<=k<=j-1)

此外如果对这段字符串进行压缩,那么我们可以枚举循环节,用Hash来判断

如果k是一个循环节,那么有f[i][j]=min(f[i][j],f[i][i+k-1]+digit[len/k]+2)

其中len=j-i+1,digit表示一个数在十进制下的长度

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 110
#define BASE 151
using namespace std;
typedef unsigned long long ll;
int n,digit[M],f[M][M];
char s[M];
ll hash[M],power[M];
void Pretreatment()
{
	int i;
	for(i=1;i<=n;i++)
		digit[i]=digit[i/10]+1;
	for(power[0]=1,i=1;i<=n;i++)
		power[i]=power[i-1]*BASE;
	for(i=1;i<=n;i++)
		hash[i]=hash[i-1]*BASE+s[i];
}
int main()
{
	int i,j,k,len;
	scanf("%s",s+1);n=strlen(s+1);
	Pretreatment();
	memset(f,0x3f,sizeof f);
	for(i=1;i<=n;i++)
		f[i][i]=1;
	for(len=2;len<=n;len++)
		for(i=1;(j=i+len-1)<=n;i++)
		{
			for(k=i;k<j;k++)
				f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]);
			for(k=1;k<n;k++)
				if(len%k==0)
				{
					ll hash1=hash[j-k]-hash[i-1]*power[len-k];
					ll hash2=hash[j]-hash[i+k-1]*power[len-k];
					if(hash1!=hash2)
						continue;
					f[i][j]=min(f[i][j],f[i][i+k-1]+digit[len/k]+2);
				}
		}
	cout<<f[1][n]<<endl;
	return 0;
}


BZOJ 1090 SCOI2003 字符串折叠 动态规划+Hash

标签:bzoj   bzoj1090   动态规划   hash   

原文地址:http://blog.csdn.net/popoqqq/article/details/43061047

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!