首页 > 其他 > 详细

BZOJ 1090 字符串折叠(Hash + DP)

时间:2017-08-02 00:14:26      阅读:449      评论:0      收藏:0      [点我收藏+]

题目链接 字符串折叠

区间DP。f[l][r]为字符串在区间l到r的最小值

正常情况下 f[l][r] = min(f[l][r], f[l][l + k - 1] + f[l + k][r]);

当l到r以k为周期时 f[l][r] = min(f[l][r], 2 + sz(k) + f[l][l + (r - l + 1) / k - 1]);

判重的时候为了方便我用了哈希……当然其他方法应该也是可以的~

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)

typedef unsigned long long LL;

const int N = 210;
const int base = 233;

int f[N][N], n;
LL bin[N], Hash[N];
char s[N];

void Hashtable(){
	bin[0] = 1;
	rep(i, 1, n) bin[i] = bin[i - 1] * base;
	rep(i, 1, n) Hash[i] = Hash[i - 1] * base + s[i];
}

inline LL gethash(int l, int r){
	return Hash[r] - Hash[l - 1] * bin[r - l + 1];
}

inline int sz(int x){
	int ret = 0;
	for (; x;) ++ret, x /= 10;
	return ret;
}

inline bool judge(int l, int m, int r){
	if ((r - l + 1) % m) return 0;
	int t1 = (r - l + 1) / m;
	LL t = gethash(l, l + t1 - 1);
	for (int i = l; i <= r; i += t1)
		if (gethash(i, i + t1 - 1) != t) return 0;
	return 1;
}

int main(){

	scanf("%s", s + 1);
	n = strlen(s + 1);

	Hashtable();
	rep(i, 1, n){
		rep(j, 1, n){
			if (j - i + 1 <= n){
				int l = j, r = i + j - 1;
				f[l][r] = r - l + 1;
				rep(k, 1, i){
					f[l][r] = min(f[l][r], f[l][l + k - 1] + f[l + k][r]);
					if (judge(l, k, r)) f[l][r] = min(f[l][r], 2 + sz(k) + f[l][l + (r - l + 1) / k - 1]);
				}
			}
		}
	}

	printf("%d\n", f[1][n]);
	return 0;
}

 

BZOJ 1090 字符串折叠(Hash + DP)

原文:http://www.cnblogs.com/cxhscst2/p/7271485.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!