上海邀请赛2个题目
2011-08-18 10:59
204 查看
首先说一下DPJuice Extractor
这个DP要完成的就是区间转移,如果以水果为状态的话,无法满足无后效性,把时间离散化,然后用时间点作为状态设计DP。
然后如何转移减少复杂度,朴素的转移需要N^3的复杂度,方法为,计算第i时间切一道枚举j = (i - 1 至0)为前一刀,然后O(N)的计算区间内有多少的水果。
我们记录每个时间点之前出现的水果的位置,然后从该位置开始向前枚举于枚举迁移刀的时间同步,并且记录在这时间的水果结束时间大于等于i的个数,这样一来时间复杂度被均摊了……具体代码如下
UVA 12012
这个DP要完成的就是区间转移,如果以水果为状态的话,无法满足无后效性,把时间离散化,然后用时间点作为状态设计DP。
然后如何转移减少复杂度,朴素的转移需要N^3的复杂度,方法为,计算第i时间切一道枚举j = (i - 1 至0)为前一刀,然后O(N)的计算区间内有多少的水果。
我们记录每个时间点之前出现的水果的位置,然后从该位置开始向前枚举于枚举迁移刀的时间同步,并且记录在这时间的水果结束时间大于等于i的个数,这样一来时间复杂度被均摊了……具体代码如下
UVA 12012
/* * ===================================================================================== * * Filename: sfx.cpp * * Description: * * Version: 1.0 * Created: 08/18/2011 09:36:17 AM * Revision: none * Compiler: gcc * * Author: ronaflx * Company: hit-ACM-Group * * ===================================================================================== */ #include <cstdlib> #include <cctype> #include <cstring> #include <iterator> #include <limits> #include <cstdio> #include <cmath> #include <ctime> #include <climits> #include <algorithm> #include <functional> #include <numeric> #include <vector> #include <map> #include <set> #include <queue> #include <stack> #include <bitset> #include <list> #include <string> #include <iostream> #include <sstream> #include <fstream> #include <iomanip> #include <stdexcept> #include <utility> #include <cassert> #include <complex> using namespace std; #define LEFT(i) ((i) << 1) #define RIGHT(i) (((i) << 1) | 1) #define MID(i) ((l[i] + r[i]) >> 1) #define CC(i, v) memset(i, v, sizeof(i)) #define REP(i, l, n) for(int i = l;i < int(n);++i) #define FOREACH(con, i) for(__typeof(con.begin()) i = con.begin();i != con.end();++i) typedef long long LL; const int MAXN = 21000; struct Sfx { int i; int key[2]; bool operator < (const Sfx& s) const { return key[0] == s.key[0] ? key[1] < s.key[1] : key[0] < s.key[0]; } } sfx[MAXN], temp[MAXN]; int rank[MAXN], bucket[MAXN], height[MAXN];// rank from 0 to n - 1 //基数排序,先拍第二关键字,再第一关键字 void radixSort(Sfx* in, int n, int idx, Sfx* out) { memset(bucket, 0, sizeof(int) * (n + 1)); for (int i = 0; i < n; i++) bucket[in[i].key[idx]]++; for (int i = 1; i <= n; i++) bucket[i] += bucket[i - 1]; for (int i = n - 1; i >= 0; i--)//for down out[--bucket[in[i].key[idx]]] = in[i]; } void buildSA(const char* text, int n) { for (int i = 0; i < n; i++) { sfx[i].i = sfx[i].key[1] = i; sfx[i].key[0] = text[i]; } sort(sfx, sfx + n); for (int i = 0; i < n; i++)//下面要比较,所以全变为0 sfx[i].key[1] = 0; int wid = 1; while (wid < n) { rank[sfx[0].i] = 0; for (int i = 1; i < n; i++) rank[sfx[i].i] = rank[sfx[i - 1].i] + (sfx[i - 1] < sfx[i]); for (int i = 0; i < n; i++) { sfx[i].i = i; sfx[i].key[0] = rank[i]; sfx[i].key[1] = i + wid < n ? rank[i + wid]: 0; } radixSort(sfx, n, 1, temp); radixSort(temp, n, 0, sfx); wid <<= 1; } } void calHeight(const char* text, int* rank, int n) {//h[i] = height[rank[i]], h[i] >= h[i - 1] - 1; for(int i = 0;i < n;i++) rank[sfx[i].i] = i; for(int i = 0, k = 0, j; i < n; i++) { if (rank[i] == 0) height[rank[i]] = 0; else { if(k > 0) k-- ; for (j = sfx[rank[i] - 1].i; text[i + k] == text[j + k];k++); height[rank[i]] = k; } } } int RMQ[MAXN][20]; void buildRMQ(int n, int* height) { for(int i = 1;i <= n;i++) RMQ[i][0] = height[i - 1]; for (int j = 1; j <= log(n + 0.00) / log(2.0); j++) for (int i = 1; i + (1 << j) - 1 <= n; i++) RMQ[i][j] = min(RMQ[i][j - 1], RMQ[i + (1 << (j - 1))][j - 1]); } int queryRMQ(int a, int b) { int len = log(b - a + 1.0) / log(2.0); return min(RMQ[a][len], RMQ[b - (1 << len) + 1][len]); } int queryLCP(int a, int b) { a = rank[a] + 1; b = rank[b] + 1; if(a > b) swap(a, b); return queryRMQ(a + 1, b); } char str[MAXN]; int ans[MAXN]; int main() { int t; scanf("%d", &t); for(int k = 1;k <= t;k++) { scanf("%s", str); int n = strlen(str); buildSA(str, n); calHeight(str, rank, n); buildRMQ(n, height); memset(ans, 0, sizeof(ans)); ans[1] = n; for(int i = 0;i < n;i++) { int len = n - i; for(int j = 1;j < len;j++) { int tmp = queryLCP(i, i + j); int c = tmp / j + 1; for(int cc = 1;cc <= c;cc++) ans[cc] = max(ans[cc], cc * j); } } printf("Case #%d: ", k); for(int i = 1;i <= n;i++) printf("%d%c", ans[i], i == n ? '\n' : ' '); } return 0; }
相关文章推荐
- hdu 5092 Seam Carving 2014上海全国邀请赛——题目重现
- 【HDU】2014上海全国邀请赛——题目重现(感谢上海大学提供题目) 题解
- HDU 5097 Page Rank(矩阵模拟)——2014上海全国邀请赛——题目重现(感谢上海大学提供题目)
- HDU5092 Seam Carving(2014上海全国邀请赛——题目重现)(DP)
- 2014上海全国邀请赛——题目重现 4.24
- hdu 5090 Game with Pearls 2014上海全国邀请赛——题目重现
- 上海邀请赛 A题目 HDU 5236(dp)
- 2013ACM-ICPC杭州赛区全国邀请赛(题目重现)
- hdu 4585 Shaolin 2013 ACM-ICPC杭州赛区全国邀请赛——题目重现
- hdu 4497 GCD and LCM(2013 ACM-ICPC吉林通化全国邀请赛——题目重现)
- 山东省高校组队训练邀请赛——AC题目(4AC:3水题,1扩展欧几里得)
- 2014年上海邀请赛A Game with Pearls
- hdu5242 Game 上海邀请赛G题
- 2014上海全国邀请赛 j 题!!
- 2014上海全国邀请赛1010(hdu 5099)
- HDU5093——Battle ships(最大二分匹配)(2014上海邀请赛重现)
- Matrix67生日邀请赛顺利结束 题目内容在此发布
- 面试题目:2个鸡蛋100层楼问题
- 2014上海全国邀请赛训练总结【7/10】
- 题目,得到某个数组,比如【1,2,3】 获得其全部的排列组合,包括1个数字的。2个数字的,和三个数字的等等