洛谷P3809 【模板】后缀排序

题目背景

这是一道模板题。

题目描述

读入一个长度为 nn 的由大小写英文字母或数字组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符在原串中的位置。位置编号为 11 到 nn 。

输入输出格式

输入格式:

一行一个长度为 nn 的仅包含大小写英文字母或数字的字符串。

输出格式:

一行,共n个整数,表示答案。

输入输出样例

输入样例#1: 复制

ababa

输出样例#1: 复制

5 3 1 4 2

说明

n <= 10^6n<=106

更新了一下自己写的后缀数组

看了一晚上还是有些地方不理解。

明天继续搞

// luogu-judger-enable-o2
#include<cstring>
#include<iostream>
#include<cstdio>
using namespace std;
const int MAXN=1e6+10;
int sa[MAXN],tax[MAXN],rak[MAXN],tp[MAXN],a[MAXN],N,M;
char s[MAXN];
int pd(int *f,int x,int y,int l)
{
    return (f[x]==f[y]&&f[x+l]==f[y+l]);
}
void Q_sort()
{
    for(int i=0;i<=M;i++) tax[i]=0;
    for(int i=1;i<=N;i++) tax[rak[i]]++;
    for(int i=1;i<=M;i++) tax[i]+=tax[i-1];
    for(int i=N;i>=1;i--) sa[ tax[rak[tp[i]]]-- ] = tp[i];
}
void S_sort()
{
    M=127;
    for(int i=1;i<=N;i++) rak[i]=a[i],tp[i]=i;Q_sort();
    for(int w=1,p=1;p<N;w=w+w,M=p)
    {
        p=0;
        for(int i=1;i<=w;i++) tp[++p]=N-w+i;
        for(int i=1;i<=N;i++)
            if(sa[i]>w) tp[++p]=sa[i]-w;
        Q_sort();swap(tp,rak);rak[sa[1]]=p=1;
        for(int i=2;i<=N;i++)
            rak[sa[i]]=pd(tp,sa[i],sa[i-1],w)?p:++p;
    }
    for(int i=1;i<=N;i++)
        printf("%d ",sa[i]);
}
int main()
{
    #ifdef WIN32
    freopen("a.in","r",stdin);
    #else
    #endif
    scanf("%s",s);
    N=strlen(s);
    for(int i=0;i<N;i++) a[i+1]=s[i]-48;
    S_sort();
}

原文地址:https://www.cnblogs.com/zwfymqz/p/8410892.html

时间: 2024-08-02 20:41:48

洛谷P3809 【模板】后缀排序的相关文章

洛谷P1158 导弹拦截 排序

---恢复内容开始--- 洛谷P1158 导弹拦截 排序 算是有技巧的枚举吧 题意 用两套系统来拦截导弹,一个系统的费用等于这个系统拦截的导弹中离他最远的那颗导弹和系统的距离 的平方 排序 将每颗导弹按距离系统1 的距离排序,然后枚举n--0 选这些导弹为系统1最远能够拦截的导弹 然后就可以更新下一次 系统2要拦截的导弹 中离系统2 最远的一颗 1 #include <cstdio> 2 #include <cmath> 3 #include <cstdlib> 4 #

AC自动机(附洛谷P3769模板题)

首先,介绍一下AC自动机(Aho-Corasick automaton),是一种在一个文本串中寻找每一个已给出的模式串的高效算法. 在学习AC自动机之前,你需要先学习Trie树和KMP算法,因为AC自动机正式利用并结合了两者的思想. 说到实际的不同,其实AC自动机只是在Trie树上引入了一个类似KMP中next数组的东西叫做Fail指针. 对于每一个节点,Fail指针指向该节点所代表的字符串中,次长的.在Trie树中存在的后缀(因为最长的在Trie树种存在的后缀就是其本身)所代表的节点. 举例:

【C++】最近公共祖先LCA(Tarjan离线算法)&amp;&amp; 洛谷P3379LCA模板

1.前言 首先我们介绍的算法是LCA问题中的离线算法-Tarjan算法,该算法采用DFS+并查集,再看此算法之前首先你得知道并查集(尽管我相信你如果知道这个的话肯定是知道并查集的),Tarjan算法的优点在于相对稳定,时间复杂度也比较居中,也很容易理解(个人认为). 2.思想 下面详细介绍一下Tarjan算法的思想: 1.任选一个点为根节点,从根节点开始. 2.遍历该点u所有子节点v,并标记这些子节点v已被访问过. 3.若是v还有子节点,返回2,否则下一步. 4.合并v到u上. 5.寻找与当前点

洛谷P3375 [模板]KMP字符串匹配

To 洛谷.3375 KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了. 输入输出格式 输入格式: 第一行为一个字符串,即为s1(仅包含大写字母) 第二行为一个字符串,即为s2(仅包含大写字母) 输出格式: 若干行,每行包含一个整数,表示s2在s1中出现的位置 接下来1行,包括length(s2)个整

洛谷.3803.[模板]多项式乘法(FFT)

题目链接:洛谷.LOJ. FFT相关:快速傅里叶变换(FFT)详解.FFT总结.从多项式乘法到快速傅里叶变换. #include <cmath> #include <cctype> #include <cstdio> #include <algorithm> #define gc() getchar() const int N=1e6+5; const double PI=acos(-1); int n,m; struct Complex { double

洛谷.1919.[模板]A乘B Problem升级版(FFT)

题目链接:洛谷.BZOJ2179 //将乘数拆成 a0*10^n + a1*10^(n-1) + ... + a_n-1的形式 //可以发现多项式乘法就模拟了竖式乘法 所以用FFT即可 注意处理进位 //n位*n位最多就只有2n位了 //论putchar的速度..还是快的 #include <cmath> #include <cstdio> #include <cctype> #include <algorithm> #define gc() getchar

洛谷1368 工艺 - 后缀数组

题意:输入一个串,通过环形变换使它最小.(n<=300000) 裸的后缀排序啊! (卡常把命都卡掉了) 后缀数组记得开大啊 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int x[1200005],y[1200005],u[1200005],v[1200005],r[1200005],o[1200005],n,m=700000; 5 int str[600005],buf[600005]; 6 7 int main(){ 8

洛谷——P1155 双栈排序

题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1不为空,将S1栈顶元素弹出至输出序列 操作c 如果输入序列不为空,将第一个元素压入栈S2 操作d 如果栈S2不为空,将S2栈顶元素弹出至输出序列 如果一个1~n的排列P可以通过一系列操作使得输出序列为1,2,…,(n-1),n,Tom就称P是一个“可双栈排序排列”.例如(1,3,2,4)就是一个“可

洛谷 [P2483] [模板] k短路

人生中的第一道黑题... 其实就是k短路模板 #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <cstdlib> #include <queue> using namespace std; const int MAXN=400005; int init(){ int