[NOI2015]品酒大会(后缀树+DP)
后缀自动机有一个性质。
就是如果倒建SAM两个串的lcp就是这两个串的结束节点的LCA。
然后就可以愉快的跑DP了。
对于每一个后缀树上的节点\(u\),它对\(len[u]\)的贡献是\(\sum_{v1}\sum_{v2\neq{v1}}size[v1]*size[v2]\)当然如果u就是一个后缀的结尾就要加上自己。
然后最大值怎么办?我们在每一个节点上维护最小次小,最大次大然后DP转移就行。
因为这题\(k\)相似就是\(k-1\)相似。最后还要对个数求个和,对最大值求一个\(max\)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define int long long
const int N=601000;
const int INF=1e18+10;
int cnt,head[N];
int tot=1,u=1,trans[N][27],size[N],len[N],fa[N];
int mx[N],mxx[N],mn[N],mnn[N],dp[N];
int ans[N],anss[N],n,a[N];
char s[N];
struct edge{
int to,nxt;
}e[N];
void add(int u,int v){
cnt++;
e[cnt].nxt=head[u];
e[cnt].to=v;
head[u]=cnt;
}
int read(){
int sum=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'||ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
return sum*f;
}
void ins(int id,int c){
int x=++tot;len[x]=len[u]+1;
mx[x]=mn[x]=a[id];size[x]=1;mxx[x]=-INF;mnn[x]=INF;
for(;u&&trans[u][c]==0;u=fa[u])trans[u][c]=x;
if(u==0)fa[x]=1;
else{
int v=trans[u][c];
if(len[u]+1==len[v])fa[x]=v;
else{
int w=++tot;len[w]=len[u]+1;
mx[w]=-INF;mn[w]=INF;mxx[x]=-INF;mnn[x]=INF;
memcpy(trans[w],trans[v],sizeof(trans[w]));
fa[w]=fa[v];
fa[x]=fa[v]=w;
for(;u&&trans[u][c]==v;u=fa[u])trans[u][c]=w;
}
}
u=x;
}
void dfs(int u){
int tmp=size[u];
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
dfs(v);
dp[u]+=size[v]*tmp;
tmp+=size[v];
if(mx[v]>mx[u]){
mxx[u]=mx[u];
mx[u]=mx[v];
if(mxx[v]>mxx[u])mxx[u]=mxx[v];
}
else if(mx[v]>mxx[u])mxx[u]=mx[v];
if(mn[v]<mn[u]){
mnn[u]=mn[u];
mn[u]=mn[v];
if(mnn[v]<mnn[u])mnn[u]=mnn[v];
}
else if(mn[v]<mnn[u])mnn[u]=mn[v];
size[u]+=size[v];
}
ans[len[u]]+=dp[u];
if(size[u]!=1)anss[len[u]]=max(anss[len[u]],max(mx[u]*mxx[u],mn[u]*mnn[u]));
}
signed main(){
scanf("%lld",&n);
scanf("%s",s+1);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
for(int i=n;i>=1;i--)ins(i,s[i]-'a'+1);
for(int i=1;i<=tot;i++)add(fa[i],i);
for(int i=0;i<=n+1;i++)anss[i]=-INF;
dfs(1);
for(int i=n;i>=0;i--)ans[i]+=ans[i+1],anss[i]=max(anss[i],anss[i+1]);
for(int i=0;i<n;i++)
if(ans[i]==0)printf("0 0\n");
else printf("%lld %lld\n",ans[i],anss[i]);
return 0;
}
[NOI2015]品酒大会(后缀树+DP)的更多相关文章
- 【BZOJ 4199】[Noi2015]品酒大会 后缀自动机+DP
题意 两个长度为$r$的子串相等称为$r$相似,两个$r$相似的权值等于子串开头位置权值乘积,给定字符串和每个位置权值,求$r$相似子串数量和最大权值乘积 对反串建立后缀自动机得到后缀树,后缀树上两个 ...
- uoj 131/bzoj 4199 [NOI2015]品酒大会 后缀树+树d
题目大意 见uoj131 分析 题目的提示还是很明显的 \(r\)相似就就代表了\(0...r-1\)相似 建出后缀树我们能dfs算出答案 再后缀和更新一下即可 注意 细节挺多的,但数据很良心 不然我 ...
- bzoj 4199: [Noi2015]品酒大会 后缀树
题目大意: 给定一个长为n的字符串,每个下标有一个权\(w_i\),定义下标\(i,j\)是r相似的仅当\(r \leq LCP(suf(i),suf(j))\)且这个相似的权为\(w_i,w_j\) ...
- BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]
4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...
- [UOJ#131][BZOJ4199][NOI2015]品酒大会 后缀数组 + 并查集
[UOJ#131][BZOJ4199][NOI2015]品酒大会 试题描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个 ...
- [NOI2015] 品酒大会 - 后缀数组,并查集,STL,启发式合并
[NOI2015] 品酒大会 Description 对于每一个 \(i \in [0,n)\) 求有多少对后缀满足 LCP 长度 \(\le i\) ,并求满足条件的两个后缀权值乘积的最大值. So ...
- 【BZOJ4199】[Noi2015]品酒大会 后缀数组+并查集
[BZOJ4199][Noi2015]品酒大会 题面:http://www.lydsy.com/JudgeOnline/wttl/thread.php?tid=2144 题解:听说能用SAM?SA默默 ...
- 【bzoj4199】[Noi2015]品酒大会 后缀自动机求后缀树+树形dp
题目描述(转自百度文库) 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项,吸引了众多品酒师参加. 在大会的晚餐上,调酒 ...
- BZOJ.4199.[NOI2015]品酒大会(后缀自动机 树形DP)
BZOJ 洛谷 后缀数组做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 只考虑求极长相同子串,即所有后缀之间的LCP. 而后缀的LCP在后缀树的LCA处.同差异这道题,在每个点处 ...
- 洛谷P2178 [NOI2015]品酒大会(后缀自动机 线段树)
题意 题目链接 Sol 说一个后缀自动机+线段树的无脑做法 首先建出SAM,然后对parent树进行dp,维护最大次大值,最小次小值 显然一个串能更新答案的区间是\([len_{fa_{x}} + 1 ...
随机推荐
- 基于vue项目的js工具方法汇总
以下是个人过去一年在vue项目的开发过程中经常会用到的一些公共方法,在此进行汇总,方便以后及有需要的朋友查看~ let util = {}; /** * @description 日期格式化 * @p ...
- Node_进阶_1
第一天 1.1简介 Node.js简介 V8引擎本身就是用于Chrome浏览器的JS解释部分,Ryan Dahl把这个V8搬到了服务器上,用于做服务器的软件. Node.js是一个让Javascrip ...
- docker 镜像的导入导出
今天使用docker部署asp.net core应用程序时,发现当我们做好基础镜像之后需要把镜像导出到正式环境,因此学习了一下如何从docker中导出镜像: 1.首先通过docker images命令 ...
- Redis:持久化之RDB和AOF
Redis:持久化之RDB和AOF RDB(Redis DataBase) 在指定的时间间隔内将内存中的数据集快照写入硬盘 也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里. R ...
- Golang-and-package-version-managment
参考文章 学习Golang之后对golang中的版本管理,包管理等机制一直没有很好的琢磨,偶然想起还是觉得很有必要进行归纳,包管理使用起来简单,无非就是install,uninstall,list等, ...
- 创业笔记-Node.js入门之一个完整的基于Node.js的web应用
用例 我们来把目标设定得简单点,不过也要够实际才行: 用户可以通过浏览器使用我们的应用. 当用户请求http://domain/start时,可以看到一个欢迎页面,页面上有一个文件上传的表单. 用户可 ...
- Cocos2d-x 3.4 之 消灭星星 > 第三篇(终) <
***************************************转载请注明出处:http://blog.csdn.net/lttree************************** ...
- Android提高UI性能技巧
提高UI性能的方法事实上有非常多在实际的开发中都已经用到了,在此做一下总结. 1.降低主线程的堵塞时间 若一个操作的耗时较长(超过5秒),我们应该将其放入后台线程中运行.仅仅在须要改动UI界面时通知主 ...
- CentOS6.3升级GCC到GCC4.8.2
server上安装的GCC版本号过旧.已经不满足个人使用的版本号需求,故决定对其进行升级操作.由当前版本号3.4.6升级到4.8.2.然受权限制约.仅仅能安装到个人文件夹.因此假设您的server能够 ...
- 【甘道夫】Hadoop2.2.0环境使用Sqoop-1.4.4将Oracle11g数据导入HBase0.96,并自己主动生成组合行键
目的: 使用Sqoop将Oracle中的数据导入到HBase中,并自己主动生成组合行键! 环境: Hadoop2.2.0 Hbase0.96 sqoop-1.4.4.bin__hadoop-2.0.4 ...