F - Common Prefixes

该题也是囤了好久的题目了,看题目公共前缀,再扫一眼题目,嗯求每个后缀与其他后缀的公共前缀的和,那不就是后缀数组吗?对于这类问题后缀数组可是相当在行的。

我们用后缀数组的思想转化下题意就是:

经过后缀排序,我们得到\(height\)数组,考虑排名从小到大依次处理每一个字符串,显然对于一个后缀i而言\(ans(sa[i])=\sum_{j=2}^{i} min_{k=j}^i (a_k)+\sum_{j=i+1}^{n} min_{k=i+1}^j(a_k)\)这样我们可以考虑拆开考虑,只考虑起一个\(\sum\)的结果,可以发现如果我们有办法做第一个的话,第二个只需要到这循环做一遍就可以了。接下来我们只考虑第一个\(\sum\)如何快速计算,一般这种题都有两种思路要么是根据某种数据结构达到快速查询到所需结果的目的,要么是根据i和i-1的关系来从上一个值递推出这个值得结果。第一种办法显然有点想不通,考虑第二种结果,我们将i从1递增看看到底有什么关系,

\(i=1\) 答案为空集

\(i=2\) \(ans=a_2\)

\(i=3\) \(ans=min(a_2,a_3)+a_3\)

\(i=4\) \(ans=min(a_2,a_3,a_4)+min(a_3,a_4)+a_4\)

\(...\)

大致可以得到些结论,当i从2开始递增时,每次都会新增一个数\(a_i\)并且对当前所有的数都和\(a_i\)取min再操作。也就是说,我们每次都要和新来的数比大小,看当前保存的数能否比他小,若新来的数比较小的话就取代之前的数,这不就是单调栈吗?我们可以维护一个递增的单调栈,并且维护下每个数出现的次数,若有元素出站,就将它的次数累加到将它弹出站的元素身上。

查看代码

//不等,不问,不犹豫,不回头.
#include
#define _ 0
#define ls p<<1
#define db double
#define rs p<<1|1
#define P 1000000007
#define ll long long
#define INF 1000000000
#define get(x) x=read()
#define PLI pair
#define PII pair
#define ull unsigned long long
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(x,y,z) for(int x=y;x<=z;++x)
#define fep(x,y,z) for(int x=y;x>=z;--x)
#define go(x) for(RE int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
using namespace std;
const int N=2e6+10;
int n,tax[N],rak[N],sa[N],tp[N],height[N],M;
int sack[N],top,cnt[N];
ll ans[N];
char c[N]; inline int read()

{

int x=0,ff=1;

char ch=getchar();

while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}

while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}

return x*ff;

} inline void Qsort()

{

rep(i,0,M) tax[i]=0;

rep(i,1,n) tax[rak[i]]++;

rep(i,1,M) tax[i]+=tax[i-1];

fep(i,n,1) sa[tax[rak[tp[i]]]--]=tp[i];

} inline void Suffixsort()

{

M=75;

rep(i,1,n) rak[i]=c[i]-'0'+1,tp[i]=i;

Qsort();

for(int w=1,p=0;p<n;M=p,w<<=1)

{

p=0;

rep(i,1,w) tp[++p]=n-w+i;

rep(i,1,n) if(sa[i]>w) tp[++p]=sa[i]-w;

Qsort();

swap(tp,rak);

rak[sa[1]]=p=1;

rep(i,2,n) rak[sa[i]]=(tp[sa[i]]tp[sa[i-1]]&&tp[sa[i]+w]tp[sa[i-1]+w])?p:++p;

}

} inline void get_height()

{

int j,k=0;

rep(i,1,n)

{

if(k) k--;

j=sa[rak[i]-1];

while(c[i+k]==c[j+k]) ++k;

height[rak[i]]=k;

}

} inline void solve()

{

rep(i,1,n) ans[i]+=n-i+1;

ll p=0;

rep(i,2,n)

{

int ct=1;

while(top&&height[i]<=height[sack[top]])

{

p-=(ll)height[sack[top]]cnt[top];

ct+=cnt[top];

top--;

}

sack[++top]=i;cnt[top]=ct;

p+=(ll)height[sack[top]]
cnt[top];

ans[sa[i]]+=p;

}

top=0;p=0;

fep(i,n-1,1)

{

int ct=1;

while(top&&height[i+1]<=height[sack[top]])

{

p-=(ll)height[sack[top]]cnt[top];

ct+=cnt[top];

top--;

}

sack[++top]=i+1;cnt[top]=ct;

p+=(ll)height[sack[top]]
cnt[top];

ans[sa[i]]+=p;

}

rep(i,1,n) putl(ans[i]);

} int main()

{

//freopen("1.in","r",stdin);

get(n);

scanf("%s",c+1);

Suffixsort();

get_height();

solve();

return (0_0);

}

//以吾之血,铸吾最后的亡魂.

AtCoder Beginner Contest 213 F题 题解的更多相关文章

  1. AtCoder Beginner Contest 215 F题题解

    F - Dist Max 2 什么时候我才能突破\(F\)题的大关... 算了,不说了,看题. 简化题意:给定\(n\)个点的坐标,定义没两个点的距离为\(min(|x_i-x_j|,|y_i-y_j ...

  2. AtCoder Beginner Contest 137 F

    AtCoder Beginner Contest 137 F 数论鬼题(虽然不算特别数论) 希望你在浏览这篇题解前已经知道了费马小定理 利用用费马小定理构造函数\(g(x)=(x-i)^{P-1}\) ...

  3. AtCoder Beginner Contest 068 ABCD题

    A - ABCxxx Time limit : 2sec / Memory limit : 256MB Score : 100 points Problem Statement This contes ...

  4. AtCoder Beginner Contest 053 ABCD题

    A - ABC/ARC Time limit : 2sec / Memory limit : 256MB Score : 100 points Problem Statement Smeke has ...

  5. AtCoder Beginner Contest 220部分题(G,H)题解

    刚开始的时候被E题卡住了,不过发现是个数学题后就开始使劲推式子,幸运的是推出来了,之后的F题更是树形DP换根的模板吧,就草草的过了,看了一眼G,随便口胡了一下,赶紧打代码,毕竟时间不多了,最后也没打完 ...

  6. AtCoder Beginner Contest 188 F - +1-1x2 思维题

    题目描述 给你两个数 \(x\),\(y\) 可以对 \(x\) 进行 \(+1,-1\) 或 \(\times 2\) 的操作 问最少操作多少次后变为 \(y\) \(x,y \leq 10^{18 ...

  7. AtCoder Beginner Contest 069 ABCD题

    题目链接:http://abc069.contest.atcoder.jp/assignments A - K-City Time limit : 2sec / Memory limit : 256M ...

  8. AtCoder Beginner Contest 070 ABCD题

    题目链接:http://abc070.contest.atcoder.jp/assignments A - Palindromic Number Time limit : 2sec / Memory ...

  9. AtCoder Beginner Contest 057 ABCD题

    A - Remaining Time Time limit : 2sec / Memory limit : 256MB Score : 100 points Problem Statement Dol ...

随机推荐

  1. 深入学习Composer原理(二)

    本系列的第二篇文章,这次我们聊聊:spl_autoload_register()函数 PHP的SPL库作为扩展库,已经于5.3.0版本后默认保持开启,成为PHP的一组强大的核心扩展库.大家有时间可以多 ...

  2. Shell系列(4)- 历史命令

    格式:history [选项] [历史命令保存文件] 选项: -c:清空历史命令 -w:把缓存中的历史命令写入到历史命令保存文件~ /.bash_history;用户的家目录下 例子: [root@l ...

  3. javascript wchar_t 宽字符 转化为 ascii字符码数组

    String.prototype.charCodeAt String.fromCharCode() String.prototype.toUtfArray = function() { return ...

  4. Uncaught TypeError: upload is not a function at HTMLInputElement.onclick

    js 中标签的id名称不能和方法名一样, <tr> <td><input type="button" id="login" val ...

  5. pyqt5读取文本框内容,输出到日志框(QTextBrowser)

    import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QAction,QLabel,QLineEdit,QPushButt ...

  6. P4640-[BJWC2008]王之财宝【OGF,Lucas定理】

    正题 题目链接:https://www.luogu.com.cn/problem/P4640 题目大意 \(n\)种物品,其中\(t\)种物品是有个数限制的,第\(i\)种限制为\(b_i\),求选出 ...

  7. 腾讯的表妹告诉我怎么学Python,今天就教我搭建Python环境和基本语法,我【码上开始】

    本文首发公众号:码上开始 环境准备 Pycharm Python3 window10/win7 安装 Python 打开Python官网地址 下载 executable installer,x86 表 ...

  8. Springboot实现VNC的反向代理

    背景 ​ 用户需要通过前端HTML页面的noVNC(noVNC是什么?)客户端连接底层VNC Server服务端,为了防止VNC Server的IP暴露,因此需要做一层代理.正常情况下使用Nginx. ...

  9. kubectl 的插件管理工具krew

    k8s的命令行工具kubectl 对于玩k8s 的人来说是必备工具.kubectl插件机制在Kubernetes 1.14宣布稳定,进入GA状态.kubectl的插件机制就是希望允许开发者以独立的二进 ...

  10. Hbase修复工具Hbck

    因为前面Hbase2集群出现过一次故障,当时花了一个周末才修好,就去了解整理了一些hbase故障的,事故现场可以看前面写的一篇:Hbase集群挂掉的一次惊险经历 一. HBCK一致性 一致性是指Reg ...