后缀自动机有一个性质。

就是如果倒建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)的更多相关文章

  1. 【BZOJ 4199】[Noi2015]品酒大会 后缀自动机+DP

    题意 两个长度为$r$的子串相等称为$r$相似,两个$r$相似的权值等于子串开头位置权值乘积,给定字符串和每个位置权值,求$r$相似子串数量和最大权值乘积 对反串建立后缀自动机得到后缀树,后缀树上两个 ...

  2. uoj 131/bzoj 4199 [NOI2015]品酒大会 后缀树+树d

    题目大意 见uoj131 分析 题目的提示还是很明显的 \(r\)相似就就代表了\(0...r-1\)相似 建出后缀树我们能dfs算出答案 再后缀和更新一下即可 注意 细节挺多的,但数据很良心 不然我 ...

  3. bzoj 4199: [Noi2015]品酒大会 后缀树

    题目大意: 给定一个长为n的字符串,每个下标有一个权\(w_i\),定义下标\(i,j\)是r相似的仅当\(r \leq LCP(suf(i),suf(j))\)且这个相似的权为\(w_i,w_j\) ...

  4. BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]

    4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...

  5. [UOJ#131][BZOJ4199][NOI2015]品酒大会 后缀数组 + 并查集

    [UOJ#131][BZOJ4199][NOI2015]品酒大会 试题描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个 ...

  6. [NOI2015] 品酒大会 - 后缀数组,并查集,STL,启发式合并

    [NOI2015] 品酒大会 Description 对于每一个 \(i \in [0,n)\) 求有多少对后缀满足 LCP 长度 \(\le i\) ,并求满足条件的两个后缀权值乘积的最大值. So ...

  7. 【BZOJ4199】[Noi2015]品酒大会 后缀数组+并查集

    [BZOJ4199][Noi2015]品酒大会 题面:http://www.lydsy.com/JudgeOnline/wttl/thread.php?tid=2144 题解:听说能用SAM?SA默默 ...

  8. 【bzoj4199】[Noi2015]品酒大会 后缀自动机求后缀树+树形dp

    题目描述(转自百度文库) 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项,吸引了众多品酒师参加. 在大会的晚餐上,调酒 ...

  9. BZOJ.4199.[NOI2015]品酒大会(后缀自动机 树形DP)

    BZOJ 洛谷 后缀数组做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 只考虑求极长相同子串,即所有后缀之间的LCP. 而后缀的LCP在后缀树的LCA处.同差异这道题,在每个点处 ...

  10. 洛谷P2178 [NOI2015]品酒大会(后缀自动机 线段树)

    题意 题目链接 Sol 说一个后缀自动机+线段树的无脑做法 首先建出SAM,然后对parent树进行dp,维护最大次大值,最小次小值 显然一个串能更新答案的区间是\([len_{fa_{x}} + 1 ...

随机推荐

  1. 页面定制CSS代码初探(一):页面变宽 文本自动换行 图片按比缩放

    初识博客 初写博客,先在设置里选了个喜欢的模板 第一眼就爱上了呢!那极简的风格,我喜欢!!但是,应用后,却发现... 纳尼!模板上右侧那张漂亮的图片呢?!我的怎么什么都没有.没有图片好难看啊,瞬间无爱 ...

  2. 关于css3背景图片渐变的规则

    1. Webkit引擎的CSS3径向渐变语法        Webkit引擎下的老版本语法:-webkit-gradient([<type>],[<position> || & ...

  3. C语言基本语法——字符串

    1.什么是字符串 2.字符串与普通字符数组的区别 3.字符串的定义方式 4.字符串的使用 5.什么是字符串数组 6.字符串数组的赋值 7.字符串数组的遍历 1.什么是字符串 • 用双引号引起来的多个字 ...

  4. linux 源码包安装拾遗

    源码包安装和apt-get/yum的区别 安装前的区别:概念上的区别 rpm和dpkg包是经过编译过的包,并且其安装位置由厂商说了算,厂商觉得安装在哪里合适,就会装在哪里,而源码包则是没有经过编译的文 ...

  5. [NOIPlus]斗地主

    毫无意义的一道题. 用pai[i]表示某种点数的牌的剩余量,used[i]表示单,对,三,四的出牌数,大力分类讨论,大力dfs即可...真奇葩... #include <iostream> ...

  6. ElasticSearch启动报错,bootstrap checks failed

    修改elasticsearch.yml配置文件,允许外网访问. vim config/elasticsearch.yml# 增加 network.host: 0.0.0.0 启动失败,检查没有通过,报 ...

  7. a标签设置高度不生效问题

    <a>是内联元素 必须设置成块级元素block 才能有width和height 不过你可以又定义display:block再定义成display:inline 以避免在IE6下产生BUG ...

  8. 洛谷P5238 整数校验器

    看到没有边读入边处理的,我来水一发 我们要看一下有那些情况是格式不合法的 单独的负号 -0(后面可以有其他数字) 0 +(后面一些数字) 我们用快速读入的方法 读取字符进行处理 还有可能超出范围的 考 ...

  9. Ajax原理-重点

    Ajax原理 AJAX即“Asynchronous Javascript And XML”,是指一种创建交互式网页应用的网页开发技术.AJAX 是一种用于创建快速动态网页的技术.它可以令开发者只向服务 ...

  10. Nginx 实现反向代理

    Nginx 实现反向代理 两个域名指向同一台 Nginx 服务器,用户访问不同的域名显示不同的网页内容 两个域名分别是 www.test1.com www.test2.com 1.准备工作 下载及安装 ...