首页 > 代码库 > BZOJ 1090 字符串折叠(Hash + DP)
BZOJ 1090 字符串折叠(Hash + DP)
题目链接 字符串折叠
区间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)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。