后缀排序板子

中暑排序

我就放个板子然后随便提点啥了

大体思路:倍增+计数排序

然后注意一个非常强的剪枝,当排名的数量等于\(n\)时,直接拿掉,而不是非要跑\(\log n\)次排序。这个剪枝在字符集比较小的时候几乎没用,但字符集小跑的本身就比较快,在字符集大的时候非常强,基本只会排序3~4次。

#include <cstdio>
#include <cstring>
#include <algorithm>
const int N=1e6+10;
int Rank[N],sa[N],tax[N],sec[N],n,m,t1,t2;
char s[N];
void Rsort()
{
    for(int i=1;i<=m;i++) tax[i]=0;
    for(int i=1;i<=n;i++) ++tax[Rank[i]];
    for(int i=2;i<=m;i++) tax[i]+=tax[i-1];
    for(int i=n;i;i--) sa[tax[Rank[sec[i]]]--]=sec[i];
}
bool cmp(int x,int y,int len){return sec[x]==sec[y]&&sec[x+len]==sec[y+len];}
void SuffixSort()
{
    scanf("%s",s+1);n=strlen(s+1);
    for(int i=1;i<=n;i++) Rank[i]=s[i],sec[i]=i;
    m=128;Rsort();
    for(int w=1,p=1,i;p<n;w<<=1,m=p)
    {
        for(p=0,i=n-w+1;i<=n;i++) sec[++p]=i;
        for(i=1;i<=n;i++) if(sa[i]>w) sec[++p]=sa[i]-w;
        Rsort(),std::swap(Rank,sec);
        Rank[sa[1]]=p=1;
        for(i=2;i<=n;i++)
            Rank[sa[i]]=cmp(sa[i],sa[i-1],w)?p:++p;
    }
}
int main()
{
    SuffixSort();
    for(int i=1;i<=n;i++) printf("%d ",sa[i]);
    return 0;
}


2018.12.15

原文地址:https://www.cnblogs.com/ppprseter/p/10122852.html

时间: 2024-12-27 22:44:51

后缀排序板子的相关文章

uoj35 后缀排序

题目链接:http://uoj.ac/problem/35 这是一道模板题. 读入一个长度为 n 的由小写英文字母组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符在原串中的位置.位置编号为 1 到 n. 除此之外为了进一步证明你确实有给后缀排序的超能力,请另外输出 n?1 个整数分别表示排序后相邻后缀的最长公共前缀的长度. 输入格式 一行一个长度为 n 的仅包含小写英文字母的字符串. 输出格式 第一行 n 个整数,第 i 个整数表示排名为 i 的后缀

后缀排序(codevs 1500)

题目描述 Description 天凯是MIT的新生.Prof. HandsomeG给了他一个长度为n的由小写字母构成的字符串,要求他把该字符串的n个后缀(suffix)从小到大排序. 何谓后缀?假设字符串是S=S1S2--Sn,定义Ti=SiSi+1--Sn.T1, T2, -, Tn就叫做S的n个后缀. 关于字符串大小的比较定义如下(比较规则和PASCAL中的定义完全相同,熟悉PASCAL的同学可以跳过此段): 若A是B的前缀,则A<B:否则令p满足:A1A2-Ap-1=B1B2-Bp-1,

uoj #35. 后缀排序

这是一道模板题. 读入一个长度为 n n 的由小写英文字母组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符在原串中的位置.位置编号为 1 1 到 n n. 除此之外为了进一步证明你确实有给后缀排序的超能力,请另外输出 n?1 n?1 个整数分别表示排序后相邻后缀的最长公共前缀的长度. 输入格式 一行一个长度为 n n 的仅包含小写英文字母的字符串. 输出格式 第一行 n n 个整数,第 i i 个整数表示排名为 i i 的后缀的第一个字符在原串中的位

1500 后缀排序

1500 后缀排序 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 查看运行结果 题目描述 Description 天凯是MIT的新生.Prof. HandsomeG给了他一个长度为n的由小写字母构成的字符串,要求他把该字符串的n个后缀(suffix)从小到大排序. 何谓后缀?假设字符串是S=S1S2……Sn,定义Ti=SiSi+1……Sn.T1, T2, …, Tn就叫做S的n个后缀. 关于字符串大小的比较定义如下(比较规则和PASCAL中的定义完全

luogu P3809 【模板】后缀排序

二次联通门 : luogu P3809 [模板]后缀排序 /* luogu P3809 [模板]后缀排序 后缀数组 sa表示 排名为i的是第几个后缀 求出sa数组后输出即可 */ #include <cstdio> #include <cstring> #define Max 1000008 void read (int &now) { register char word = getchar (); for (now = 0; word < '0' || word

codevs1500 后缀排序

题目描述 Description 天凯是MIT的新生.Prof. HandsomeG给了他一个长度为n的由小写字母构成的字符串,要求他把该字符串的n个后缀(suffix)从小到大排序. 何谓后缀?假设字符串是S=S1S2……Sn,定义Ti=SiSi+1……Sn.T1, T2, …, Tn就叫做S的n个后缀. 关于字符串大小的比较定义如下(比较规则和PASCAL中的定义完全相同,熟悉PASCAL的同学可以跳过此段): 若A是B的前缀,则A<B:否则令p满足:A1A2…Ap-1=B1B2…Bp-1,

后缀排序

后缀数组板子,给出一个字符串,要求输出sa数组. 首先声明一下各数组的作用. rank:序列上的点->点权; sa:排名->位置; tmp:辅助数组; #include<cstdio> #include<cstring> #define N 1000050 int rank[N],tmp[N],sa[N],hs[N],num[N]; int n; char s[N]; bool cmp(int i,int j,int k) { if(i+k>n||j+k>n

hdu3518 Boring Counting[后缀排序]

裸的统计不同的重复出现子串(不重叠)种数的题.多次使用后缀排序要注意小细节.y数组在重复使用时一定要清空,看那个line25 +k就明白了 ,cnt也要清空,为什么就不说了 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;} 5 temp

P5353 【模板】树上后缀排序

题目地址:[模板]树上后缀排序 我们尝试把普通 SA 改成树上 SA,所以先把普通 SA 贴上来. namespace SA { int sa[N], rk[N], tp[N], tx[N]; inline void tsort() { for (int i = 1; i <= m; i++) tx[i] = 0; for (int i = 1; i <= n; i++) ++tx[rk[i]]; for (int i = 1; i <= m; i++) tx[i] += tx[i-1]