名称:字符串

来源:2019年陕西省选

链接

博客链接

题目链接

题目内容

题目描述

给出一个长度为\(n\)的由小写字母组成的字符串\(a\),设其中第\(i\)个字符为\(a_i(1≤i≤n)\)。

设删掉第\(i\)个字符之后得到的字符串为\(s_i\),请按照字典序对\(s_1,s_2,……,s_n\)从小到大排序。若两个字符串相等,则认为编号小的字符串字典序更小。

格式

输入

第一行一个整数\(n\)。

第二行一个长为\(n\)的由小写字母组成的字符串\(a\)。

输出

输出一行\(n\)个整数\(k_1,k_2,……,k_n\),用空格隔开。表示$ s_{k_1}<s_{k_2}<……<s_{k_n} $。

数据

样例

输入

7
aabaaab

输出

3 7 4 5 6 1 2

数据范围

对于所有数据, \(1\leq n\leq10^6\) 。

对于10%的数据, \(1\leq n\leq2000\) 。

对于另外20%的数据,\(1\leq n\leq10^5\) 。且任意两个相邻字符\(a_i,a_{i+1}\)不相等;

对于另外30%的数据,\(1\leq n\leq10^5\)。

对于余下40%的数据,无特殊限制。

提示

本题不需要SA或者SAM等高级算法。

题解

10分

暴力构造出\(s\),再用快速排序进行排序。时间复杂度为\(O(n^2log(n))\),在\(n\leq2000\)的数据下跑得过。

30分

注意到:其中20%的数据没相邻两个字符不相等。

引理

当其任意两个字符不相等时,\(s_i\)和\(s_j(i<j)\)的大小关系实际上就是\(a_{i+1}\)与\(a_i\)的大小关系。

证明:由题意得。

\[s_i[1……i-1]=a[1……i-1]=s_j[1……i-1]\\
s_i[j……n-1]=a[j+1……n]=s_j[j……n-1]
\]

重点在于比较\(s_i[i……j-1]\)和\(s_j[i……j-1]\)的大小关系。

\(s_i[i……j-1]\)正对应\(a[i+1……j]\);

\(s_j[i……j-1]\)正对应\(a[i……j-1]\);

而\(a[i+1]!=a[i]\),故二者的大小关系可以确定。

于是,我们可以开一个双端队列。逆序处理整个字符串。

当我们发现\(a[i+1]<a[i]\)时,则说明\(s_i\)比后面的(即已经被处理过放进双端队列里的)都要小,就把数字\(i\)放在双端队列的前面;否则说明\(s_i\)比后面的都要大,就把它放在双端队列的后面。

graph TD
a(开始处理状态i)-->b{a_i+1< a_i}
b-->|yes|c[将i插在双端队列前面]
b-->|no|d[将i插在双端队列后面]
c-->e(进入下一轮操作)
d-->e

最后我们按顺序将双端队列每一个位置上的数字。

100分

那么,我们如何拿到100分呢???

实际上,我们只需要将原来30分的做法进行扩展,或者说将所有情况转换为两两相邻字符不相等的情况就行。

引理

当\(a[i]=a[i+1]\)时,\(s[i]=s[i+1]\)

证明略

由此,我们就可以将字符串连续相同的一段进行压缩,其中每一个字母都代表着原字符串的一段区间。

例如\("bbbcaa"\)压缩成\("bca"\),并且处理出来如下数据:

字母 开始位置 结束位置
b 1 3
c 4 4
a 5 6

将压缩后的串排序得\(3\quad1\quad2\)。

将原来处理出来的数据带入得\((5\quad6)(1\quad2\quad3)(4)\)。

//C++
#include<iostream>
#include<stdio.h>
#include<string>
#include<deque>
using namespace std;
const int nn=1000001;
inline void output(long long o);
int start[nn],final[nn];
inline long long input();
string a;
deque<int>k;
int main()
{
int n=input(),size=0;
cin>>a;
for(int i=0,PREV=0;i<n;i++)
{
PREV=i;
while(a[i]==a[i+1]&&i<n)i++;
a[size]=a[i],start[size]=PREV+1,final[size++]=i+1;
}
for(int i=size-1;i>=0;i--)
if(a[i+1]<a[i])k.push_front(i);
else k.push_back(i);
for(;k.front()!=k.back();k.pop_front())
for(int i=start[k.front()],f=final[k.front()];i<=f;i++)output(i),putchar(' ');
for(int i=start[k.front()],f=final[k.front()];i<f;i++)output(i),putchar(' ');
output(final[k.front()]),putchar('\n');
return 0;
}
inline void output(long long o)
{
if(o<0)putchar('-'),o=-o;
if(o>=10)output(o/10);
putchar(o%10^'0');
}
inline long long input()
{
bool positive=true;
char now=getchar();
long long i=0;
for(;!isdigit(now);now=getchar())
if(now=='-')positive=!positive;
for(;isdigit(now);now=getchar())i=(i<<3)+(i<<1)+(now^'0');
return positive?i:-i;
}

[SNOI2019]字符串的更多相关文章

  1. 【LOJ#3095】[SNOI2019]字符串(后缀数组)

    [LOJ#3095][SNOI2019]字符串(后缀数组) 题面 LOJ 题解 首先画图看看如何比较两个串的大小,发现这个东西等价于求两个相邻的后缀的\(LCP\). 一个做法是求出\(SA\),然后 ...

  2. [洛谷P5329][SNOI2019]字符串

    题目大意:给一个长度为$n$的字符串$s$,字符串$p_i$为字符串$s$去掉第$i$个字符后形成的字符串.请给所有字符串$p_i$排序(相同字符串按编号排序) 题解:先去掉所有连续相同字符,因为它们 ...

  3. luogu P5329 [SNOI2019]字符串

    传送门 显然要写一个排序,那只要考虑cmp函数怎么写就行了.第\(i\)个字符串和第 \(j\)个,首先前\(min(i,j)-1\)个字符是相同的,然后就是要比较后缀\(min(i,j)\)和\(m ...

  4. 洛谷$P5329\ [SNOI2019]$字符串 字符串

    正解:字符串 解题报告: 传送门$QwQ$ 有两个很妙的方法,分别港下$QwQ$ 首先为了表示方便,这里和题面一样设$s_i$表示去掉第$i$个字母得到的字符串.另设$lcp(i,j)$表示$suf_ ...

  5. 题解 P5329 【[SNOI2019]字符串】

    用栈的做法来水一发. 首先我们有一个暴力的做法,枚举每个被删除的字符,然后排序输出,时间复杂度:$ O ( N \times N \times LogN ) $ . 然后我们观察一下数据,发现有一个数 ...

  6. 【LOJ】#3095. 「SNOI2019」字符串

    LOJ#3095. 「SNOI2019」字符串 如果两个串\(i,j\)比较\(i < j\),如果离\(a_{i}\)最近的不同的数是\(a_{k}\),如果\(j < k\)那么\(i ...

  7. 「SNOI2019」字符串

    题目 看起来非常一眼啊,我们完全可以\(std::sort\)来解决这歌问题 于是现在的问题转化成了比较函数怎么写 随便画一下就会发现前面的好几位是一样的,后面的好几位也是一样,只需要比较中间的一段子 ...

  8. [日常] SNOI2019场外VP记

    SNOI2019场外VP记 教练突然说要考一场别省省选来测试水平...正好还没看题那就当VP咯w... Day 1 八点开题打 .vimrc. 先看了看题目名...一股莫名鬼畜感袭来... 怎么T1就 ...

  9. Python高手之路【六】python基础之字符串格式化

    Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...

随机推荐

  1. WAMP运行原理

    Apache运行原理 Apache的诸多功能都是通过模块进行加载的,自己本身并不具备那么多功能. php文件动态网页请求原理 请求步骤: 1. 用户在浏览器中输入需要访问的网站的域名以及具体要请求的网 ...

  2. HTTP_5_通信数据转发程序:代理、网关、隧道

    HTTP通信时,除客户端和服务器之外,还有一些用于通信数据转发的应用程序,例如代理,网关,隧道.配合服务器工作. 代理 转发功能,客户端与服务器之间可有多个代理, 缓存代理:减少服务器压力,透明代理: ...

  3. 消费端如何保证消息队列MQ的有序消费

    消息无序产生的原因 消息队列,既然是队列就能保证消息在进入队列,以及出队列的时候保证消息的有序性,显然这是在消息的生产端(Producer),但是往往在生产环境中有多个消息的消费端(Consumer) ...

  4. CEPH RGW多 ZONE的配置

    相关的名称解释 Region :可以理解为区域,是基于地理位置的逻辑划分:如:华南,华北之类,包含多个region的Ceph集群必须指定一个master region,一个region可以包含一个或者 ...

  5. jQuery插件之路(一)——试着给jQuery的一个Carousel插件添加新的功能

    前几日在网上看到了一个关于Carousel插件的教学视频,于是也顺便跟着学习着做了一下.但是在做完之后发现,在别的网站上面看到类似的效果要比现在做的这个要多一个功能,也就是在底下会有一些按钮,当鼠标放 ...

  6. python基础--基于套接字进行文件传输、异常处理、socketserver模块

    异常处理: 什么是异常处理: 程序在运行过程中出现了不可预知的错误,并且该错误没有对应的处理机制,那么就会以异常的形式表现出来,造成的影响就是整个程序无法再正常运行 异常的结构: 异常的类型.异常的信 ...

  7. .Net Core 最优 MD5 打开方式!初学者建议收藏(支持 SHA1,SHA256,.Net Framework)

    public static string GetMd5Hash(string input) { using (MD5 md5Hash = MD5.Create()) { // Convert the ...

  8. 用python实现银行家算法

    编制模拟银行家算法的程序,并以下面给出的例子验证所编写的程序的正确性. 进程 已占资源 最大需求数 资源种类 A B C D A B C D P0 0 0 1 2 0 0 1 2 P1 1 0 0 0 ...

  9. ABAP-根据采购订单行项目统计供应商未清额和已清额

    1.传入和传出表结构都是一样的: FUNCTION zmm_fm_po_invence. *"------------------------------------------------ ...

  10. 洛谷 P3195 [HNOI2008]玩具装箱TOY

    题意简述 有n个物体,第i个长度为ci 将n个物体分为若干组,每组必须连续 如果把i到j的物品分到一组,则该组长度为 \( j - i + \sum\limits_{k = i}^{j}ck \) 求 ...