【Luogu5108】仰望半月的夜空(后缀数组)
【Luogu5108】仰望半月的夜空(后缀数组)
题面
题解
实名举报这题在比赛之前还不是这个样子的,还被我用SAM给水过去了
很明显求出\(SA\)之后就是按照\(SA\)的顺序从前往后考虑每一个长度,这样可以知道串是什么。
不过如果串相同要左端点最靠左,所以二分包含这个串的区间,用\(RMQ\)求出区间最小值即可。
(其实就是拿来复习SA板子的)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAX 400200
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n,sig;
char ch[MAX];
int S[MAX],tot,a[MAX],lg[MAX];
int t[MAX],x[MAX],y[MAX],rk[MAX],SA[MAX],hg[20][MAX],mn[20][MAX];
bool cmp(int i,int j,int k){return y[i]==y[j]&&y[i+k]==y[j+k];}
void GetSA()
{
int m=tot;
for(int i=1;i<=n;++i)t[x[i]=a[i]]++;
for(int i=1;i<=m;++i)t[i]+=t[i-1];
for(int i=n;i>=1;--i)SA[t[x[i]]--]=i;
for(int k=1;k<=n;k<<=1)
{
int p=0;
for(int i=n-k+1;i<=n;++i)y[++p]=i;
for(int i=1;i<=n;++i)if(SA[i]>k)y[++p]=SA[i]-k;
for(int i=1;i<=m;++i)t[i]=0;
for(int i=1;i<=n;++i)t[x[y[i]]]++;
for(int i=1;i<=m;++i)t[i]+=t[i-1];
for(int i=n;i>=1;--i)SA[t[x[y[i]]]--]=y[i];
swap(x,y);x[SA[1]]=p=1;
for(int i=2;i<=n;++i)x[SA[i]]=cmp(SA[i],SA[i-1],k)?p:++p;
if(p>=n)break;m=p;
}
for(int i=1;i<=n;++i)rk[SA[i]]=i;
for(int i=2;i<=n;++i)lg[i]=lg[i>>1]+1;
for(int i=1,j=0;i<=n;++i)
{
if(j)--j;
while(a[i+j]==a[SA[rk[i]-1]+j])++j;
hg[0][rk[i]]=j;
}
for(int j=1;j<=lg[n];++j)
for(int i=1;i+(1<<j)-1<=n;++i)
hg[j][i]=min(hg[j-1][i],hg[j-1][i+(1<<(j-1))]);
for(int i=1;i<=n;++i)mn[0][i]=SA[i];
for(int j=1;j<=lg[n];++j)
for(int i=1;i+(1<<j)-1<=n;++i)
mn[j][i]=min(mn[j-1][i],mn[j-1][i+(1<<(j-1))]);
}
int lcp(int i,int j)
{
if(i==j)return 1e9;i=rk[i];j=rk[j];
if(i>j)swap(i,j);i+=1;int k=lg[j-i+1];
return min(hg[k][i],hg[k][j-(1<<k)+1]);
}
int RMQ(int i,int j)
{
if(i>j)swap(i,j);int k=lg[j-i+1];
return min(mn[k][i],mn[k][j-(1<<k)+1]);
}
int main()
{
sig=read();n=read();
if(sig==26)
{
scanf("%s",ch+1);n=strlen(ch+1);
for(int i=1;i<=n;++i)a[i]=ch[i]-96;
}
else for(int i=1;i<=n;++i)a[i]=read();
for(int i=1;i<=n;++i)S[++tot]=a[i];
sort(&S[1],&S[n+1]);tot=unique(&S[1],&S[n+1])-S-1;
for(int i=1;i<=n;++i)a[i]=lower_bound(&S[1],&S[tot+1],a[i])-S;
GetSA();
for(int i=1,p=1;i<=n;++i)
{
while(n-SA[p]+1<i)++p;
int l=p+1,r=n,ret=p;
while(l<=r)
{
int mid=(l+r)>>1;
if(lcp(SA[p],SA[mid])>=i)l=mid+1,ret=mid;
else r=mid-1;
}
printf("%d ",RMQ(p,ret));
}
puts("");return 0;
}
【Luogu5108】仰望半月的夜空(后缀数组)的更多相关文章
- 洛谷P5108 仰望半月的夜空(后缀数组)
题意 题目链接 Sol warning:下面这个做法只有95分,本地拍了1w+组都没找到错误我表示十分无能为力 我们考虑每个串的排名去更新答案,显然排名为\(1\)的后缀的前缀一定是当前长度的字典序最 ...
- luoguP5108 仰望半月的夜空 [官方?]题解 后缀数组 / 后缀树 / 后缀自动机 + 线段树 / st表 + 二分
仰望半月的夜空 题解 可以的话,支持一下原作吧... 这道题数据很弱..... 因此各种乱搞估计都是能过的.... 算法一 暴力长度然后判断判断,复杂度\(O(n^3)\) 期望得分15分 算法二 通 ...
- 洛谷 P5108 仰望半月的夜空 解题报告
P5108 仰望半月的夜空 题目描述 半月的夜空中,寄托了多少人与人之间的思念啊 曦月知道,这些思念会汇集成一个字符串\(S(n = |S|)\) 由于思念汇集的过于复杂,因此曦月希望提炼出所有的思念 ...
- 后缀数组的倍增算法(Prefix Doubling)
后缀数组的倍增算法(Prefix Doubling) 文本内容除特殊注明外,均在知识共享署名-非商业性使用-相同方式共享 3.0协议下提供,附加条款亦可能应用. 最近在自学习BWT算法(Burrows ...
- BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]
4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...
- BZOJ 1692: [Usaco2007 Dec]队列变换 [后缀数组 贪心]
1692: [Usaco2007 Dec]队列变换 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1383 Solved: 582[Submit][St ...
- POJ3693 Maximum repetition substring [后缀数组 ST表]
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9458 Acc ...
- POJ1743 Musical Theme [后缀数组]
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 27539 Accepted: 9290 De ...
- 后缀数组(suffix array)详解
写在前面 在字符串处理当中,后缀树和后缀数组都是非常有力的工具. 其中后缀树大家了解得比较多,关于后缀数组则很少见于国内的资料. 其实后缀数组是后缀树的一个非常精巧的替代品,它比后缀树容易编程实现, ...
随机推荐
- BootStrap学习(3)_导航菜单
一.导航元素 1.表格导航或标签 以一个带有 class .nav 的无序列表开始. 添加 class .nav-tabs. <!DOCTYPE html> <html xmlns= ...
- 手机端@media的屏幕适配
@media only screen and (width: 320px) { html { font-size: 16px; }} @media only screen and (width: 36 ...
- 【php增删改查实例】第十五节 - 用户管理模块(删除确认)
假如有一天,用户找到你,说万一不小心手一抖,就点击了删除用户,不太好.能不能再误点的时候,再给个确认框,让用户进行二次确认. OK,用户是上帝.这边我们可以考虑用confirm方法进行开发. 参考代码 ...
- 异步编程(async&await)
前言 本来这篇文章上个月就该发布了,但是因为忙 QuarkDoc 一直没有时间整理,所以耽搁到今天,现在回归正轨. C# 5.0 虽然只引入了2个新关键词:async和await.然而它大大简化了异步 ...
- 微服务之Sping Cloud
版本说明 Finchley SR2 价值简要 微服务之间是松耦合,跨不同业务部门,提供非常充分的灵活性,加快项目开发完成效率,方便组件化独立可扩展性及复用. 微服务应用结构表现 组件简要 1. Eur ...
- Linux下DNS服务(Bind9)之Web管理利器-NamedManager部署说明
NamedManager 是一个基于Web的DNS管理系统,可用来添加.调整和删除DNS的zones/records数据.它使用Bind作为底层DNS服务,提供一个现代Ajax的Web界面,支持 IP ...
- Uniform Generator HDU1014
题意 给你公式seed(x+1) = [seed(x) + STEP] % MOD ,输入step和mod, 问你是否可以从第一项0,算到mod,它们是否都不同 是 good choice 否则 ba ...
- 代码规范与复审2——个人博客作业week
一.关于编程规范的重要性论证 1.不支持. 1)编程规范有利于自己提高编程效率和编程质量.编码是程序员的职责,一个好的信息技术产品必然有高质量的代码,高质量的代码首先 一点它必须遵守某种编程规范.如果 ...
- throws和throw抛出异常的使用规则
一直对java中的throws和throw不太理解.最近一直在查这两个方面的资料,算是能明白一点吧.如果我下面的观点哪有不对,希望指出来,我加以改进. throw:(针对对象的做法) ...
- suqid透明正向代理
如果想实现透明正向代理,则必需将用户的网关IP指向 Squid 服务器,而此后便无需再修改浏览器选项 在命令行 <菜单+R> 中使用 ping 命令: ping www.baidu.c ...