题目链接

题意分析

给你一个字符串 让你求\(1-n\)长度下的字符串的中字典序最小并且最靠左的字符串的开头位置

我们考虑先建出\(SA\)

然后考虑对于一个字符串后缀排序之后

baba

后缀排序之后 先不管位置 只关心字典序

数字代表当前更新长度

a 1
aba 2 3
ba
baba 4

我们可以发现 第二个后缀还可以更新长度为\(1\)的子串

所以我们考虑使用二分 求刚好可以满足的位置

然后我们再使用\(RMQ\)求这些位置中对应原串位置最靠左的位置

然后更新即可

CODE:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<string>
#include<queue>
#include<map>
#include<stack>
#include<list>
#include<set>
#include<deque>
#include<vector>
#include<ctime>
#define ll long long
#define inf 0x7fffffff
#define N 500008
#define IL inline
#define M 608611
#define D double
#define ull unsigned long long
#define R register
using namespace std;
template<typename T>IL void read(T &_)
{
T __=0,___=1;char ____=getchar();
while(!isdigit(____)) {if(____=='-') ___=0;____=getchar();}
while(isdigit(____)) {__=(__<<1)+(__<<3)+____-'0';____=getchar();}
_=___ ? __:-__;
}
/*-------------OI使我快乐-------------*/
char s[M];
int n,key,have;int num[M],res[M],ans[M];
int ST[M][20][2],lg[M];
int SA[M],rnk[M],cdy[M],wzy[M],vis[M],hei[M];
IL void Rsort()
{
for(R int i=0;i<=key;++i) vis[i]=0;
for(R int i=1;i<=n;++i) vis[cdy[i]]++;
for(R int i=1;i<=key;++i) vis[i]+=vis[i-1];
for(R int i=n;i;--i) SA[vis[cdy[wzy[i]]]--]=wzy[i];
}
IL void get_SA()
{
for(R int i=1;i<=n;++i) cdy[i]=num[i],wzy[i]=i;Rsort();
for(R int x=1;x<=n;x<<=1)
{
int cnt=0;
for(R int i=n-x+1;i<=n;++i) wzy[++cnt]=i;
for(R int i=1;i<=n;++i) if(SA[i]>x) wzy[++cnt]=SA[i]-x;
Rsort();swap(cdy,wzy);cdy[SA[cnt=1]]=1;
for(R int i=2;i<=n;++i)
cdy[SA[i]]=(wzy[SA[i]]==wzy[SA[i-1]]&&wzy[SA[i]+x]==wzy[SA[i-1]+x] ? cnt:++cnt);
if(cnt==n) break;
else key=cnt;
}
}
IL void get_hei()
{
for(R int i=1;i<=n;++i) rnk[SA[i]]=i;
int lat,k=0;
for(R int i=1;i<=n;++i)
{
if(k) --k;
lat=SA[rnk[i]-1];
while(num[lat+k]==num[i+k]) ++k;
hei[rnk[i]]=k;
}
}
IL void pre()
{
for(R int i=1;(1<<i)<=300000;++i) lg[1<<i]=i;
for(R int i=2;i<=300000;++i) if(!lg[i]) lg[i]=lg[i-1];
for(R int i=1;i<=n;++i) ST[i][0][0]=hei[i];
for(R int j=1;(1<<j)<=n;++j)
for(R int i=1;i<=n;++i)
ST[i][j][0]=min(ST[i][j-1][0],ST[i+(1<<(j-1))][j-1][0]);
for(R int i=1;i<=n;++i) ST[i][0][1]=SA[i];
for(R int j=1;(1<<j)<=n;++j)
for(R int i=1;i<=n;++i)
ST[i][j][1]=min(ST[i][j-1][1],ST[i+(1<<(j-1))][j-1][1]);
}
IL int qury_hei(int le,int ri)
{
if(le>ri) swap(le,ri);++le;int lx=lg[ri-le+1];
return min(ST[le][lx][0],ST[ri-(1<<lx)+1][lx][0]);
}
IL int qury_min(int le,int ri)
{
if(le>ri) swap(le,ri);int lx=lg[ri-le+1];
return min(ST[le][lx][1],ST[ri-(1<<lx)+1][lx][1]);
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
read(have);read(n);
if(have==26)
{
scanf("%s",s+1);key=130;
for(R int i=1;i<=n;++i) num[i]=s[i]-'0'+1;
}
else
{
for(R int i=1;i<=n;++i) read(num[i]),res[i]=num[i];
sort(res+1,res+n+1);key=unique(res+1,res+n+1)-res-1;
for(R int i=1;i<=n;++i) num[i]=lower_bound(res+1,res+key+1,num[i])-res;
// for(R int i=1;i<=n;++i)
// printf("%d%c",num[i],(i==n ? '\n':' '));
// printf("key %d\n",key);
}
get_SA();get_hei();pre();
// printf("SA : ");for(R int i=1;i<=n;++i) printf("%d%c",SA[i],(i==n ? '\n':' '));
// printf("height : ");for(R int i=1;i<=n;++i) printf("%d%c",hei[i],(i==n ? '\n':' '));
for(R int i=1,tail=1;i<=n;++i)
{
while(tail<n&&n-SA[tail]+1<i) ++tail;
//维护单调指针
ans[i]=SA[tail];
int le=tail+1,ri=n,can=-1;
while(le<=ri)
{
int mid=(le+ri)>>1;
if(qury_hei(tail,mid)>=i) can=mid,le=mid+1;
else ri=mid-1;
}
//二分那个位置 用lcp判断是否可以满足贡献出那个串
if(can!=-1) ans[i]=min(ans[i],qury_min(tail,can));
//存在的话 我们就用中间最左端的位置更新
}
for(R int i=1;i<=n;++i) printf("%d%c",ans[i],(i==n ? '\n':' '));
// fclose(stdin);
// fclose(stdout);
return 0;
}

HEOI 2019 RP++

P5108 仰望半月的夜空的更多相关文章

  1. 洛谷 P5108 仰望半月的夜空 解题报告

    P5108 仰望半月的夜空 题目描述 半月的夜空中,寄托了多少人与人之间的思念啊 曦月知道,这些思念会汇集成一个字符串\(S(n = |S|)\) 由于思念汇集的过于复杂,因此曦月希望提炼出所有的思念 ...

  2. 洛谷P5108 仰望半月的夜空(后缀数组)

    题意 题目链接 Sol warning:下面这个做法只有95分,本地拍了1w+组都没找到错误我表示十分无能为力 我们考虑每个串的排名去更新答案,显然排名为\(1\)的后缀的前缀一定是当前长度的字典序最 ...

  3. P5108 仰望半月的夜空 SAM+线段树覆盖

    $ \color{#0066ff}{ 题目描述 }$ 半月的夜空中,寄托了多少人与人之间的思念啊 曦月知道,这些思念会汇集成一个字符串\(S(n = |S|)\) 由于思念汇集的过于复杂,因此曦月希望 ...

  4. 【Luogu5108】仰望半月的夜空(后缀数组)

    [Luogu5108]仰望半月的夜空(后缀数组) 题面 洛谷 题解 实名举报这题在比赛之前还不是这个样子的,还被我用SAM给水过去了 很明显求出\(SA\)之后就是按照\(SA\)的顺序从前往后考虑每 ...

  5. luoguP5108 仰望半月的夜空 [官方?]题解 后缀数组 / 后缀树 / 后缀自动机 + 线段树 / st表 + 二分

    仰望半月的夜空 题解 可以的话,支持一下原作吧... 这道题数据很弱..... 因此各种乱搞估计都是能过的.... 算法一 暴力长度然后判断判断,复杂度\(O(n^3)\) 期望得分15分 算法二 通 ...

  6. Luogu 5108 仰望半月的夜空(后缀数组)

    如果是要求左端点最大,直接求出SA,找前缀名次最小值就可以了.虽然现在要左端点最小,但我们已经知道了这个字典序最小的串是什么,找到名次数组上的合法区间求最小值即可.我也不知道为什么我会弃掉这个题,可能 ...

  7. 【LGP5108】仰望半月的夜空

    题目 我还会写\(SA\)和 \(ST\)表真是令人感动 发现这是一个思博题 我们开一个指针,标记一下当前合法的字典序最小的后缀排名在哪里,刚开始自然是\(1\) 我们发现这个后缀不能为我们提供\(i ...

  8. 伙伴们休息啦canvas绘图夜空小屋

    HTML5 canvas绘图夜空小屋 伙伴们园友们,夜深了,休息啦,好人好梦... 查看效果:http://hovertree.com/texiao/html5/28/ 效果图如下: 代码如下: &l ...

  9. HTML5夜空烟花绽放动画效果

    模板描述:HTML5夜空烟花绽放动画效果基于HTML5 canvas制作,模拟夜空烟花绽放动画效果,烟花会在夜空打出贺词,有新年快乐.合家幸福.万事如意.心想事成.财源广进等,文字可以自定义,做成各种 ...

随机推荐

  1. XPath在python中的高级应用

    XPath在python的爬虫学习中,起着举足轻重的地位,对比正则表达式 re两者可以完成同样的工作,实现的功能也差不多,但XPath明显比re具有优势,在网页分析上使re退居二线. XPath介绍: ...

  2. Lucas–Kanade光流算法学习

    Lucas–Kanade光流算法是一种两帧差分的光流估计算法.它由Bruce D. Lucas 和 Takeo Kanade提出.         光流(Optical flow or optic f ...

  3. 洛谷 P3112 [USACO14DEC]后卫马克Guard Mark

    题目描述 Farmer John and his herd are playing frisbee. Bessie throws the frisbee down the field, but it' ...

  4. Greeplum 系列(四) 实战

    Greeplum 系列(四) 实战 表结构 (1) 拉链表结构 create table public.member_fatdt0 ( member_id varchar(64), phoneno v ...

  5. Java Persistence with MyBatis 3(中文版) 第一章 MyBatis入门

    本章将涵盖以下话题: ž  MyBatis是什么? ž  为什么选择MyBatis? ž  MyBatis安装配置 ž  域模型样例 1.1 MyBatis是什么 MyBatis是一个简化和实现了Ja ...

  6. <<C++标准程序库>>中的STL简单学习笔记

    0. 内容为个人学习笔记, 仅供参考, 如有错漏, 欢迎指正! 1. STL中的所有组件都是由模板构成的, 所以其元素可以是任意型别的. 组件有: - 容器: 管理某类对象的集合. 不同的容器有各自的 ...

  7. 前端实用软件: Markdown工具之---Typora实用技巧(总结)

    Typora是一款超简洁的markdown编辑器,具有如下特点: 完全免费,目前已支持中文 跨平台,支持windows,mac,linux 支持数学公式输入,图片插入 极其简洁,无多余功能 界面所见即 ...

  8. CoderForces 518D Ilya and Escalator (期望DP)

    题意:给定 n 个人,在每一时刻一个人进入地铁的概率是 p,站着不动的概率是 1-p,然后问你 t 时间地铁里有多少人. 析:很明显这是一个期望DP,用d[i][j]表示 i 时刻 j 个人进入地铁的 ...

  9. mybatis SqlMapConfig.xml

    一.SqlMapConfig.xml 1.属性properties 在入门时,以抽取出连接数据库的属性得到properties文件. a.可以通过resource和url来获得属性. b.proper ...

  10. Java对称加密算法

    对称加密算法概念 加密密钥和解密密钥相同,大部分算法加密揭秘过程互逆. 特点:算法公开.(相比非对称加密)计算量小.加密速度快.效率高. 弱点:双方都使用同样的密钥,安全性得不到保证. 常用对称加密算 ...