BZOJ 4199: [Noi2015]品酒大会( 后缀数组 + 并查集 )
2016-01-24 22:22
429 查看
求出后缀数组后, 对height排序, 从大到小来处理(r相似必定是0~r-1相似), 并查集维护. 复杂度O(NlogN + Nalpha(N))
-----------------------------------------------------------------------------------
#include<cstdio>#include<cstring>#include<algorithm> using namespace std; typedef long long ll; const ll INF = -1LL << 60;const int maxn = 300009; char S[maxn];int w[maxn], N;int cnt[maxn], Sa[maxn], Rank[maxn], Height[maxn];int mx[maxn], mn[maxn], fa[maxn], sz[maxn], r[maxn];ll ans[maxn], tot[maxn]; void Init() { scanf("%d%s", &N, S); for(int i = 0; i < N; i++) scanf("%d", w + i); S[N++] = '$';} void Build() { int m = 255, *x = Height, *y = Rank; for(int i = 0; i < m; i++) cnt[i] = 0; for(int i = 0; i < N; i++) cnt[x[i] = S[i]]++; for(int i = 1; i < m; i++) cnt[i] += cnt[i - 1]; for(int i = N; i--; ) Sa[--cnt[x[i]]] = i; for(int k = 1, p = 0; k <= N; k <<= 1, p = 0) { for(int i = N - k; i < N; i++) y[p++] = i; for(int i = 0; i < N; i++) if(Sa[i] >= k) y[p++] = Sa[i] - k; for(int i = 0; i < m; i++) cnt[i] = 0; for(int i = 0; i < N; i++) cnt[x[y[i]]]++; for(int i = 1; i < m; i++) cnt[i] += cnt[i - 1]; for(int i = N; i--; ) Sa[--cnt[x[y[i]]]] = y[i]; swap(x, y), x[Sa[0]] = 0, p = 1; for(int i = 1; i < N; i++) { if(y[Sa[i]] != y[Sa[i - 1]] || y[Sa[i] + k] != y[Sa[i - 1] + k]) p++; x[Sa[i]] = p - 1; } if((m = p) >= N) break; } for(int i = 0; i < N; i++) Rank[Sa[i]] = i; Height[0] = 0; for(int i = 0, h = 0; i < N; i++) if(Rank[i]) { if(h) h--; while(S[i + h] == S[Sa[Rank[i] - 1] + h]) h++; Height[Rank[i]] = h; }} int Find(int x) { return x == fa[x] ? x : fa[x] = Find(fa[x]);} bool Cmp(const int &l, const int &r) { return Height[l] > Height[r];} inline void Max(ll &x, ll t) { if(t > x) x = t;}inline void Max(int &x, int t) { if(t > x) x = t;}inline void Min(int &x, int t) { if(t < x) x = t;} void Work() { for(int i = 0; i < N; i++) { sz[i] = 1; r[i] = fa[i] = i; mx[i] = mn[i] = w[i]; tot[i] = 0; ans[i] = INF; } sort(r, r + N, Cmp); for(int i = 0; i < N; i++) if(r[i] > 1) { int u = Find(Sa[r[i]]), v = Find(Sa[r[i] - 1]); if(u == v) continue; tot[Height[r[i]]] += ll(sz[u]) * sz[v]; Max(ans[Height[r[i]]], max(ll(mx[u]) * mx[v], ll(mn[u]) * mn[v])); fa[u] = v, sz[v] += sz[u]; Max(mx[v], mx[u]); Min(mn[v], mn[u]); } for(int i = Height[r[0]]; i--; ) tot[i] += tot[i + 1], Max(ans[i], ans[i + 1]); for(int i = 0; i + 1 < N; i++) printf("%lld %lld\n", tot[i], ans[i] != INF ? ans[i] : 0);} int main() { Init(); Build(); Work(); return 0;}-----------------------------------------------------------------------------------
相关文章推荐
- Java final修饰词
- PHP send email configuration in XAMPP
- CentOS 6.4 编译安装LLVM3.3,Clang和Libc++
- 【BZOJ】1004 Cards
- 归档文件中异常的 EOF
- 基于JAVA的Promise模式实现
- Android Studio 单元测试
- 表格标签
- struts2的坑以及tomcat的一些常识
- Android之AndroidStudio使用
- 简易下拉
- Linux输入子系统(Input Subsystem)
- java final
- Android高级之网络框架封装
- iOS-自定义Model转场动画-仿酷我音乐播放器效果
- 85.Count Primes
- restlet Framework2.2和2.3版本的对比
- 大型网站架构系列:消息队列(二)
- IOS实战之项目架构
- 名词解释之人身保险概论