传送门

显然要写一个排序,那只要考虑cmp函数怎么写就行了.第\(i\)个字符串和第

\(j\)个,首先前\(min(i,j)-1\)个字符是相同的,然后就是要比较后缀\(min(i,j)\)和\(min(i,j)+1\),先求lcp(要对\(max(i,j)-min(i,j)\)取\(min\)),如果两个后缀往后跳lcp的位置字符不一样就可以得到结果了.

然后可以用SA求lcp 然后我T了,但是可以发现所有lcp都是相邻两个后缀的,所以这个可以\(O(n)\)递推

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<ctime>
#include<queue>
#include<map>
#include<set>
#define LL long long
#define db double using namespace std;
const int N=2e6+10;
int rd()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
} char cc[N];
int /*sa[N],rk[N],wr[N],wx[N],bk[N],*/he[N]/*,mi[N][21],L2[N]*/,n,an[N];
/*void inii()
{
int sz=128,p=0,j=1;
for(int i=1;i<=n;++i) ++bk[rk[i]=cc[i]];
for(int i=1;i<=sz;++i) bk[i]+=bk[i-1];
for(int i=n;i;--i) sa[bk[rk[i]]--]=i;
while(p<n)
{
int tp=0;
for(int i=n-j+1;i<=n;++i) wx[++tp]=i;
for(int i=1;i<=n;++i) if(sa[i]>j) wx[++tp]=sa[i]-j;
for(int i=1;i<=n;++i) wr[i]=rk[wx[i]];
for(int i=1;i<=sz;++i) bk[i]=0;
for(int i=1;i<=n;++i) ++bk[wr[i]];
for(int i=1;i<=sz;++i) bk[i]+=bk[i-1];
for(int i=n;i;--i) sa[bk[wr[i]]--]=wx[i];
for(int i=1;i<=n;++i) wr[i]=rk[i];
rk[sa[1]]=p=1;
for(int i=2;i<=n;++i) rk[sa[i]]=p+=!(wr[sa[i]]==wr[sa[i-1]]&&wr[sa[i]+j]==wr[sa[i-1]+j]);
sz=p,j<<=1;
}
for(int i=1;i<=n;++i)
{
if(he[rk[i-1]]) he[rk[i]]=he[rk[i-1]]-1;
int j=sa[rk[i]-1];
while(cc[i+he[rk[i]]]==cc[j+he[rk[i]]]) ++he[rk[i]];
}
for(int i=2;i<=n;++i) L2[i]=L2[i>>1]+1;
for(int i=1;i<=n;++i) mi[i][0]=he[i];
for(int j=1;j<=L2[n];++j)
for(int i=1;i+(1<<j)-1<=n;++i)
mi[i][j]=min(mi[i][j-1],mi[i+(1<<(j-1))][j-1]);
}
int lcp(int i,int j)
{
if(i==j) return n;
i=rk[i],j=rk[j];
if(i>j) swap(i,j);
++i;
int z=L2[j-i+1];
return min(mi[i][z],mi[j-(1<<z)+1][z]);
}*/
bool cmp(int i,int j)
{
/*int ii,jj;
if(i<j) ii=i+1,jj=i;
else ii=j,jj=j+1;
int len=lcp(ii,jj);
if(ii<i) len=min(len,i-ii);
if(jj<j) len=min(len,j-jj);
ii+=len,jj+=len;
ii+=ii==i,jj+=jj==j;
if(cc[ii]!=cc[jj]) return cc[ii]<cc[jj];
return i<j;*/
int ii=min(i,j),lm=max(i,j)-ii,len=he[ii+1];
if(len>=lm) return i<j;
return (cc[ii+len]<cc[ii+1+len])^(i<j);
} int main()
{
n=rd();
scanf("%s",cc+1);
for(int i=2;i<=n;++i)
{
if(he[i-1]) he[i]=he[i-1]-1;
while(cc[i+he[i]]==cc[i-1+he[i]]) ++he[i];
}
for(int i=1;i<=n;++i) an[i]=i;
sort(an+1,an+n+1,cmp);
for(int i=1;i<=n;++i) printf("%d ",an[i]);
return 0;
}

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

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

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

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

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

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

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

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

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

  5. Luogu 1071 - 潜伏者 - [字符串]

    题目链接:https://www.luogu.org/problemnew/show/P1071 题解: 模拟就完事儿了. 注意failed的情况有:出现一个 $f[x]$ 对应多个值:存在两个不同的 ...

  6. [SNOI2019]字符串

    名称:字符串 来源:2019年陕西省选 题目内容 传送门 洛谷(P5392) 题目描述 给出一个长度为$n$的由小写字母组成的字符串$a$,设其中第$i$个字符为$a_i(1≤i≤n)$. 设删掉第$ ...

  7. luogu P4302 [SCOI2003]字符串折叠

    题目描述 折叠的定义如下: 一个字符串可以看成它自身的折叠.记作S = S X(S)是X(X>1)个S连接在一起的串的折叠.记作X(S) = SSSS-S(X个S). 如果A = A', B = ...

  8. Luogu P2679 子串(字符串+dp)

    P2679 子串 题意 题目描述 有两个仅包含小写英文字母的字符串\(A\)和\(B\). 现在要从字符串\(A\)中取出\(k\)个互不重叠的非空子串,然后把这\(k\)个子串按照其在字符串\(A\ ...

  9. luogu P6088 [JSOI2015]字符串树 可持久化trie 线段树合并 树链剖分 trie树

    LINK:字符串树 先说比较简单的正解.由于我没有从最简单的考虑答案的角度思考 所以... 下次还需要把所有角度都考察到. 求x~y的答案 考虑 求x~根+y~根-2*lca~根的答案. 那么问题变成 ...

随机推荐

  1. BZOJ 4423: [AMPPZ2013]Bytehattan 平面图转对偶图 + 并查集

    Description 比特哈顿镇有n*n个格点,形成了一个网格图.一开始整张图是完整的.有k次操作,每次会删掉图中的一条边(u,v),你需要回答在删除这条边之后u和v是否仍然连通. Input 第一 ...

  2. const与#define的区别

    1.const (1)为什么需要const成员函数? C中常用:“ #define 变量名 变量值”定义一个值替代,然而却有个致命缺点:缺乏类型检测机制,这样预处理在C++中成为可能引发错误的隐患,于 ...

  3. 7.28Assignment

    1.考试题(7.27) + 2.插头dp 4道题 0/4  before 18:00 3.cdq分治 2道题理解 0/2  before 21:00 4.点分治 2道题 0/2 before 7:00 ...

  4. codevs 1057 津津的储蓄计划 2004年NOIP全国联赛提高组 x

     时间限制: 1 s  空间限制: 128000 KB   题目描述 Description 津津的零花钱一直都是自己管理.每个月的月初妈妈给津津300元钱,津津会预算这个月的花销,并且总能做到实际花 ...

  5. windows10 gcc编译C程序(简单编译)

    参考:http://c.biancheng.net/view/660.html gcc可以一次性完成C语言源程序的编译,也可以分步骤完成:下面先介绍一次性编译过程. 1.生成可执行程序 cd xxx ...

  6. React曾经忽略的知识点(上)

    1.JSX 防注入攻击 你可以放心地在 JSX 当中使用用户输入 const title = response.potentiallyMaliciousInput; // 直接使用是安全的: cons ...

  7. [CSP-S模拟测试]:Walker(数学)

    题目传送门(内部题86) 输入格式 第一行$n$接下来$n$行,每行四个浮点数,分别表示变换前的坐标和变换后的坐标 输出格式 第一行浮点数$\theta$以弧度制表示第二行浮点数$scale$第三行两 ...

  8. CentOS7--删除virbr0

    https://blog.csdn.net/aienjoy/article/details/78994128

  9. nginx中lua主动设置Content-Length

    最近发现lua调用ngx.say和ngx.print 默认返回的HTTP头是trunk模式的,通常情况下是很好的,没有什么问题:但是要提供给其他人回源的时候就有问题了,特别是我要给slice模块回源, ...

  10. 如何使用Jetbrains Clion 在一个工程里 编译单个C++源文件 (实现一键编译且运行)

    这篇文章主要在下面这篇文章的基础上,先是实现了一键编译和一键运行两个单个功能,最后又进一步使用Clion自带的Custom Build Application实现编译且运行一键实现. https:// ...