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

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

时间:2017-08-02 00:37:10      阅读:103      评论:0      收藏:0      [点我收藏+]

标签:ble   hashtable   logs   bzoj   eth   base   其他   pre   can   

题目链接 字符串折叠

区间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)

标签:ble   hashtable   logs   bzoj   eth   base   其他   pre   can   

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

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