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. 安装Centos7,出现无法联网的问题-----解决办法

    安装Centos7,出现无法联网的问题-----解决办法 我安装的是centos7的版本 在我照着centos7安装教程-CentOS-PHP中文网这个教程安装完后 我发现我的centOS无法联网,在 ...

  2. pymysql基础教程

    pymysql基础教程 1.下载pymysql 在命令框输入指令即可 pip install pymysql 2.连接pymysql 连接数据库: import pymysql conn = pymy ...

  3. 【OWASP TOP10】2021年常见web安全漏洞TOP10排行

    [2021]常见web安全漏洞TOP10排行 应用程序安全风险 攻击者可以通过应用程序中许多的不同的路径方式去危害企业业务.每种路径方法都代表了一种风险,这些风险都值得关注. 什么是 OWASP TO ...

  4. mysql更新数据时:当想mysql某插入有某字段设置了unique且和之前相同时,会报错,并停止运行

    这个在mysql5.7会报错: 如openid设为unique: 1062 - Duplicate entry 'oTfYq6PKne00IrcTqphmKqKnsahM' for key 'qx_w ...

  5. maven编译打包

    sonar扫描java项目,需要使用maven 来到maven项目下第一件事情编译打包,注意代码扫描是在编译之后的:https://blog.csdn.net/qq_34556414/article/ ...

  6. 1.3redis小结--配置php reids拓展

    1.执行php文件 输出phpinfo();  <?php phpinfo(); 2.根据PHPinfo的信息确定需要下载的 php_redis.dll , php_igbinary.dll 版 ...

  7. 鸿蒙内核源码分析(进程管理篇) | 谁在管理内核资源 | 百篇博客分析OpenHarmonyOS | v2.07

    百篇博客系列篇.本篇为: v02.xx 鸿蒙内核源码分析(进程管理篇) | 谁在管理内核资源 | 51.c.h .o 进程管理相关篇为: v02.xx 鸿蒙内核源码分析(进程管理篇) | 谁在管理内核 ...

  8. P4351-[CERC2015]Frightful Formula【组合数学,MTT】

    正题 题目链接:https://www.luogu.com.cn/problem/P4351 题目大意 \(n*n\)的矩形,给出第一行和第一列的数,剩下的满足\(F_{i,j}=a*F_{i,j-1 ...

  9. P4428-[BJOI2018]二进制【树状数组,set】

    正题 题目链接:https://www.luogu.com.cn/problem/P4428 题目大意 长度为\(n\)的\(0/1\)串要求支持 修改一个位置 求区间\([l,r]\)有多少个子区间 ...

  10. CF990G-GCD Counting【dfs】

    正题 题目链接:https://www.luogu.com.cn/problem/CF990G 题目大意 给出一棵有点权的树,对于每个\(k\)求有多条路径的点权\(gcd\)为\(k\) \(1\l ...