【BZOJ 4199】[Noi2015]品酒大会 后缀自动机+DP
题意
两个长度为$r$的子串相等称为$r$相似,两个$r$相似的权值等于子串开头位置权值乘积,给定字符串和每个位置权值,求$r$相似子串数量和最大权值乘积
对反串建立后缀自动机得到后缀树,后缀树上两个状态的lca的长度len就是原串的两个子串的lcp,在树上进行dp,parent树上每个状态代表长度为$maxlen_s-maxlen_{pa_s}$长度的一段子串,对于相似子串数量,$r$相似子串的数量$ans_r+=Right_u\times Right_v,maxlen_u==r$,对于最大权值乘积,维护每个状态的最大值最小值,每次用最大值最大值的乘积和最小值乘最小值的乘积更新答案,最后将答案累计
时间复杂度$O(n)$
代码
#include <bits/stdc++.h>
#define inf (LL)1000000000000000001
using namespace std;
typedef long long LL;
const int N = 1001000;
int ch[N][30], pa[N], maxlen[N], sz, last, Right[N], mark[N], val[N];
inline void init_sam() {
memset(ch, 0, sizeof(ch));
last = sz = 1;
}
inline void extend(int c, int x) {
int p = last, np = ++sz; last = np; maxlen[np] = maxlen[p] + 1; mark[np] = 1; val[np] = x;
while(p && !ch[p][c]) ch[p][c] = np, p = pa[p];
if(!p) {pa[np] = 1; return;}
int q = ch[p][c];
if(maxlen[q] == maxlen[p] + 1) {
pa[np] = q;
}else {
int nq = ++sz;
memcpy(ch[nq], ch[q], sizeof(ch[q]));
pa[nq] = pa[q]; maxlen[nq] = maxlen[p] + 1; pa[q] = pa[np] = nq;
while(ch[p][c] == q) ch[p][c] = nq, p = pa[p];
}
}
int cnt, head[N], nxt[N], to[N];
inline void init_edge() {cnt = 0; memset(head, -1, sizeof(head));}
inline void add(int u, int v) {to[cnt] = v; nxt[cnt] = head[u]; head[u] = cnt++;}
int n, a[N];
LL ans1[N], ans2[N], Max[N], Min[N];
char str[N];
void dfs(int u) {
Right[u] = 0; Max[u] = -inf; Min[u] = inf;
if(mark[u]) Right[u] = 1, Max[u] = Min[u] = val[u];
for(int i = head[u]; ~i; i = nxt[i]) {
int v = to[i]; dfs(v);
if(Max[u] != -inf && Max[v] != -inf && Min[u] != inf && Min[v] != inf) {
ans2[maxlen[u]] = max(ans2[maxlen[u]], max(Max[u] * Max[v], Min[u] * Min[v]));
}
Max[u] = max(Max[u], Max[v]); Min[u] = min(Min[u], Min[v]);
ans1[maxlen[u]] += 1LL * Right[u] * Right[v];
Right[u] += Right[v];
}
}
int main() {
init_sam();
init_edge();
scanf("%d", &n);
scanf("%s", str + 1);
for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
for(int i = n; i >= 1; --i) extend(str[i] - 'a', a[i]);
for(int i = 2; i <= sz; ++i) add(pa[i], i);
for(int i = 0; i <= n; ++i) ans2[i] = -inf;
dfs(1);
for(int i = n - 1; i >= 0; --i) ans1[i] += ans1[i + 1], ans2[i] = max(ans2[i], ans2[i + 1]);
for(int i = 0; i < n; ++i) {
if(ans1[i])printf("%lld %lld\n", ans1[i], ans2[i]);
else printf("0 0\n");
}
return 0;
}
【BZOJ 4199】[Noi2015]品酒大会 后缀自动机+DP的更多相关文章
- BZOJ.4199.[NOI2015]品酒大会(后缀自动机 树形DP)
BZOJ 洛谷 后缀数组做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 只考虑求极长相同子串,即所有后缀之间的LCP. 而后缀的LCP在后缀树的LCA处.同差异这道题,在每个点处 ...
- BZOJ 4199: [Noi2015]品酒大会 后缀自动机_逆序更新
一道裸题,可以考虑自底向上去更新方案数与最大值. 没啥难的 细节........ Code: #include <cstdio> #include <algorithm> #i ...
- BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]
4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...
- BZOJ.4199.[NOI2015]品酒大会(后缀数组 单调栈)
BZOJ 洛谷 后缀自动机做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 显然只需要考虑极长的相同子串的贡献,然后求后缀和/后缀\(\max\)就可以了. 对于相同子串,我们能想 ...
- bzoj 4199: [Noi2015]品酒大会 后缀树
题目大意: 给定一个长为n的字符串,每个下标有一个权\(w_i\),定义下标\(i,j\)是r相似的仅当\(r \leq LCP(suf(i),suf(j))\)且这个相似的权为\(w_i,w_j\) ...
- BZOJ 4199: [Noi2015]品酒大会( 后缀数组 + 并查集 )
求出后缀数组后, 对height排序, 从大到小来处理(r相似必定是0~r-1相似), 并查集维护. 复杂度O(NlogN + Nalpha(N)) ------------------------- ...
- uoj 131/bzoj 4199 [NOI2015]品酒大会 后缀树+树d
题目大意 见uoj131 分析 题目的提示还是很明显的 \(r\)相似就就代表了\(0...r-1\)相似 建出后缀树我们能dfs算出答案 再后缀和更新一下即可 注意 细节挺多的,但数据很良心 不然我 ...
- 【bzoj4199】[Noi2015]品酒大会 后缀自动机求后缀树+树形dp
题目描述(转自百度文库) 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项,吸引了众多品酒师参加. 在大会的晚餐上,调酒 ...
- bzoj 4199: [Noi2015]品酒大会
Description 一年一度的"幻影阁夏日品酒大会"隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发"首席品酒家"和"首席猎手&quo ...
随机推荐
- flex弹性盒模型
flex 意思是弹性布局,用来给盒模型提供最大的灵活度,指定容器中的项目为弹性布局,类似于float:left; 比float的好处是容器没有设置高度,会根据项目来自适应高度,我们都知道,设置floa ...
- iOS开发---业务逻辑
iOS开发---业务逻辑 1. 业务逻辑 iOS的app开发的最终目的是要让用户使用, 用户使用app完成自己的事就是业务逻辑, 业务逻辑的是最显眼开发工作.但是业务逻辑对于开发任务来说, 只是露 ...
- python入门课程 第一章 课程介绍
1-1 Python入门课程介绍特点: 优雅.明确.简单适合领域: web网站和各种网络服务 系统工具和脚本 作为"胶水"语言把其他语言开发的模块包装起来方 ...
- (转)linux设备驱动之USB数据传输分析 二
3.2:控制传输过程1:root hub的控制传输在前面看到,对于root hub的情况,流程会转入rh_urb_enqueue().代码如下:static int rh_urb_enqueue (s ...
- 一篇文章彻底弄清ARC始末
本文转载至 http://blog.csdn.net/allison162004/article/details/38758265 自动引用计数(ARC)是编译器的一个特色,提供了Objective- ...
- Java内部类{[普通内部类][静态内部类]}
package Learn.com.seven; /** * * @author tqw * 本例主要学习内部类的使用 * Java的内部类分成两部分来讲: * 1:内部类 * 2:静态内部类 * * ...
- linux下查找指定时间内修改过的或新建的文件
1.简单命令 # find -type f \( -newermt '2017-04-19 00:00' -a -not -newermt '2017-04-27 23:59' \) 2.简单实现(参 ...
- iOS和Android后台机制对比
转自:http://blog.csdn.net/zsch591488385/article/details/27232881 一.iOS的“伪后台”程序 首先,先了解一下ios 中所谓的「后台进程」到 ...
- 洛谷 P3629 [APIO2010]巡逻
题目在这里 这是一个紫题,当然很难. 我们往简单的想,不建立新的道路时,从1号节点出发,把整棵树上的每条边遍历至少一次,再回到1号节点,会恰好经过每条边两次,路线总长度为$2(n-1)$,根据树的深度 ...
- 关于Android app的launcher图标更换后,仍然显示默认的ic_launcher图标的解决方法
<h1>概要</h1>在做手机适配的时候,遇到了一个很奇怪的问题,在1080x720的手机可以正常显示替换的ic_launcher.png图标,但是在1920x1080的手机上 ...