思路

在后缀树上进行一些操作就好了

后缀树上LCA的maxlen就是两个后缀的LCP的长度了

然后统计每个点作为LCA的次数和最大值、次大值、最小值、次小值

然后就做完了

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#define int long long
using namespace std;
int val[301000*2],n;
char s[301000*2];
namespace SAM{
int maxlen[301000*2],suflink[301000*2],trans[301000*2][26],endpos[301000*2],maxnum[301000*2],semaxnum[301000*2],minnum[301000*2],seminnum[301000*2],Nodecnt=1,in[301000*2],num[301000*2],maxval[301000*2];
int fir[301000*2],v[301000*2],nxt[301000*2],cnt=0;
void addedge(int ui,int vi){
++cnt;
v[cnt]=vi;
nxt[cnt]=fir[ui];
fir[ui]=cnt;
}
int New_state(int _suflink,int *_trans,int _maxlen){
++Nodecnt;
suflink[Nodecnt]=_suflink;
if(_trans)
for(int i=0;i<26;i++)
trans[Nodecnt][i]=_trans[i];
maxlen[Nodecnt]=_maxlen;
return Nodecnt;
}
int add_len(int u,int c,int inq){
int z=New_state(0,NULL,maxlen[u]+1);
endpos[z]=1;
maxnum[z]=minnum[z]=inq;
semaxnum[z]=-0x3f3f3f3f;
seminnum[z]=0x3f3f3f3f;
while(u&&trans[u][c]==0){
trans[u][c]=z;
u=suflink[u];
}
if(!u){
suflink[z]=1;
return z;
}
int v=trans[u][c];
if(maxlen[v]==maxlen[u]+1){
suflink[z]=v;
return z;
}
int y=New_state(suflink[v],trans[v],maxlen[u]+1);
endpos[y]=0;
maxnum[y]=semaxnum[y]=-0x3f3f3f3f;
minnum[y]=seminnum[y]=0x3f3f3f3f;
suflink[z]=suflink[v]=y;
while(u&&trans[u][c]==v){
trans[u][c]=y;
u=suflink[u];
}
return z;
}
void insert(char *s,int len){
reverse(s+1,s+len+1);
reverse(val+1,val+len+1);
int last=1;
for(int i=1;i<=len;i++)
last=add_len(last,s[i]-'a',val[i]);
}
void build(void){
memset(num,0,sizeof(num));
memset(maxval,-0x3f,sizeof(maxval));
for(int i=1;i<=Nodecnt;i++)
addedge(suflink[i],i);
}
void dfs(int u){
for(int i=fir[u];i;i=nxt[i]){
dfs(v[i]);
num[maxlen[u]]+=endpos[u]*endpos[v[i]];
endpos[u]+=endpos[v[i]];
if(maxnum[v[i]]>=maxnum[u]){
if(max(maxnum[u],semaxnum[v[i]])>semaxnum[u])
semaxnum[u]=max(maxnum[u],semaxnum[v[i]]);
maxnum[u]=maxnum[v[i]];
}
else if(maxnum[v[i]]>semaxnum[u]){
semaxnum[u]=maxnum[v[i]];
}
if(minnum[v[i]]<=minnum[u]){
if(min(seminnum[v[i]],minnum[u])<seminnum[u])
seminnum[u]=min(seminnum[v[i]],minnum[u]);
minnum[u]=minnum[v[i]];
}
else if(minnum[v[i]]<seminnum[u]){
seminnum[u]=minnum[v[i]];
}
}
if(endpos[u]>1)
maxval[maxlen[u]]=max(maxval[maxlen[u]],max(maxnum[u]*semaxnum[u],minnum[u]*seminnum[u]));
}
};
signed main(){
scanf("%lld",&n);
scanf("%s",s+1);
for(int i=1;i<=n;i++)
scanf("%lld",&val[i]);
SAM::insert(s,n);
SAM::build();
SAM::dfs(1);
for(int i=n;i>=0;i--){
SAM::maxval[i]=max(SAM::maxval[i],SAM::maxval[i+1]);
SAM::num[i]+=SAM::num[i+1];
}
for(int i=0;i<n;i++)
printf("%lld %lld\n",SAM::num[i],(SAM::num[i]==0)?0:SAM::maxval[i]);
return 0;
}

P2178 [NOI2015]品酒大会的更多相关文章

  1. 洛谷 P2178 [NOI2015]品酒大会 解题报告

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

  2. 洛谷P2178 [NOI2015]品酒大会 后缀数组+单调栈

    P2178 [NOI2015]品酒大会 题目链接 https://www.luogu.org/problemnew/show/P2178 题目描述 一年一度的"幻影阁夏日品酒大会" ...

  3. 洛谷P2178 [NOI2015]品酒大会

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

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

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

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

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

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

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

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

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

  8. [UOJ#131][BZOJ4199][NOI2015]品酒大会

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

  9. BZOJ_4199_[Noi2015]品酒大会_后缀自动机

    BZOJ_4199_[Noi2015]品酒大会_后缀自动机 Description 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 酒家”和“首席 ...

随机推荐

  1. ionic3 slides轮播图手动滑动后无法自动播放问题

    我们都知道Ionic3为我们提供了一套丰富易用的UI组件库,然而凡事是都有不完美之处,今天我们来看一下ionic3 slides组件在实现轮播功能时候的小问题. 先开UI小姐姐给到的3张美美哒效果图 ...

  2. 《Redis 命令操作》

    一:Redis 的启动与关闭 - 关闭指定端口的 Redis - redis-cli -p 9200 shutdown - 开启 Redis - redis-server redis.config 二 ...

  3. 你应当如何学习C++以及编程(细节是必要的,但不是重要的,把时间用在集中精力去解决问题,而不是学习新技术,那样练不成高手。在实践中提高才是最重要的。最最重要的内功还是长期学习所磨练出来的自学能力)good

    最近在学习Qt但由于没有C++的基础,感觉学的很吃力.看到pongba的这篇文章感觉不错就弄过来了, 原文地址:http://blog.csdn.net/qter_wd007/article/deta ...

  4. Linux - ansible 安装

    # 安装依赖 yum install rpm-build python2-devel sshpass PyYAML python-jinja2 python-paramiko python-six p ...

  5. JDK1.8 StampedLock: 解决ReentrantReadWriteLock在读多写少情况下,写线程饥饿问题

    ReentrantReadWriteLock 在沒有任何读写锁时,才可以取得写入锁,这可用于实现了悲观读取(Pessimistic Reading), 即如果执行中进行读取时,经常可能有另一执行要写入 ...

  6. flask shell命令

    在flask项目目录下,使用pipenv shell激活flask虚拟环境后,调用flask shell能够使用虚拟环境的python解释器进入交互式环境,并且工作目录还保留在flask项目目录. f ...

  7. 自定义bash提示符

    http://adamcavendish.is-programmer.com/posts/35659.html

  8. 为什么CentOS7中找不到mysql服务,并且还找不到mysql.sock?

    个人遇到问题的经过: 我一个月前买了云主机,UI图画好了,前端也写了,php如何开发也想好了,结果呢,安装apache是成功了,mysql看样子也是安装成功了,但是mysql根本无法运行起来,搞得我无 ...

  9. Wireshark常用过滤命令

    WireShark在我们网络编程中有非常重要的作用,可以帮我们抓取我们程序发送的数据包,大家常常说他是抓包工具,其实它是一款非常强大的网络数据包分析工具. 在WireShark的学习上,不想花费太多的 ...

  10. Android -- 《 最美有物》好看的点赞效果

    1,前天在鸿洋的公众号上看到一款不错的点赞效果,是仿最美有物的点赞,再加上自己最近学习状态很差,自己想着通过这个效果练手一下,果然,花了整整两天的时间,按照以前的效率的话一天就够了,哎,已经调整了一个 ...