题目链接

论找到一个好的教程的正确性。。

后缀数组

下标从1编号:

//299ms	2560kb
#include <cstdio>
#include <cstring>
#include <algorithm>
const int N=1e5+5; int n,sa[N],rk[N],sa2[N],tm[N],ht[N];
char s[N]; void Get_SA()
{
int *x=rk,*y=sa2,m=200;
for(int i=0; i<=m; ++i) tm[i]=0;
for(int i=1; i<=n; ++i) ++tm[x[i]=s[i]-'a'+1];
for(int i=1; i<=m; ++i) tm[i]+=tm[i-1];
for(int i=n; i; --i) sa[tm[x[i]]--]=i;
for(int p=0,k=1; k<n; k<<=1,m=p,p=0)
{
for(int i=n-k+1; i<=n; ++i) y[++p]=i;
for(int i=1; i<=n; ++i) if(sa[i]>k) y[++p]=sa[i]-k;
for(int i=0; i<=m; ++i) tm[i]=0;
for(int i=1; i<=n; ++i) ++tm[x[i]];
for(int i=1; i<=m; ++i) tm[i]+=tm[i-1];
for(int i=n; i; --i) sa[tm[x[y[i]]]--]=y[i]; std::swap(x,y), p=1, x[sa[1]]=1;
for(int i=2; i<=n; ++i)
// if(y[sa[i-1]]==y[sa[i]]&&((sa[i-1]+k<=n&&sa[i]+k<=n&&y[sa[i-1]+k]==y[sa[i]+k])||(sa[i-1]+k>n&&sa[i]+k>n))) x[sa[i]]=p;
// if(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]) x[sa[i]]=p;
// else x[sa[i]]=++p;
x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p:++p;
if(p>=n) break;
}
}
void Calc_ht()
{
for(int i=1; i<=n; ++i) rk[sa[i]]=i;
ht[1]=0;
for(int k=0,p,i=1; i<=n; ++i)//ht[rk[i]]>=ht[rk[i-1]]-1
{
if(rk[i]==1) continue;//排名为0的 ht[rk[i]]=ht[0]=0
if(k) --k;
p=sa[rk[i]-1];
while(i+k<=n&&p+k<=n&&s[i+k]==s[p+k]) ++k;
ht[rk[i]]=k;
}
} int main()
{
scanf("%s",s+1), n=strlen(s+1);
Get_SA();
for(int i=1; i<=n; ++i) printf("%d ",sa[i]);
putchar('\n'), Calc_ht();
for(int i=2; i<=n; ++i) printf("%d ",ht[i]); return 0;
}
//321ms	2552kb
#include <cstdio>
#include <cstring>
#include <algorithm>
const int N=1e5+5; int n,sa[N],rk[N],sa2[N],tm[N],ht[N];
char s[N]; void Get_SA()
{
int *x=rk,*y=sa2,m=28;
for(int i=0; i<m; ++i) tm[i]=0;
for(int i=0; i<n; ++i) ++tm[x[i]=s[i]-'a'];
for(int i=1; i<m; ++i) tm[i]+=tm[i-1];
for(int i=n-1; ~i; --i) sa[--tm[x[i]]]=i;
for(int p=0,k=1; k<n; k<<=1,/*m=p,*/m=p+1,p=0)
{
for(int i=n-k; i<n; ++i) y[p++]=i; for(int i=0; i<n; ++i) if(sa[i]>=k) y[p++]=sa[i]-k;
for(int i=0; i<m; ++i) tm[i]=0;
for(int i=0; i<n; ++i) ++tm[x[i]];
for(int i=1; i<m; ++i) tm[i]+=tm[i-1];
for(int i=n-1; ~i; --i) sa[--tm[x[y[i]]]]=y[i]; // std::swap(x,y), p=1, x[sa[0]]=0;
// for(int i=1; i<n; ++i)
// if(y[sa[i-1]]==y[sa[i]]&&((sa[i-1]+k<n&&sa[i]+k<n&&y[sa[i-1]+k]==y[sa[i]+k])||(sa[i-1]+k>=n&&sa[i]+k>=n))) x[sa[i]]=p-1;
// else x[sa[i]]=p++;
// if(p>=n) break;
std::swap(x,y), p=0, x[sa[0]]=0;
for(int i=1; i<n; ++i)
if(y[sa[i-1]]==y[sa[i]]&&((sa[i-1]+k<n&&sa[i]+k<n&&y[sa[i-1]+k]==y[sa[i]+k])||(sa[i-1]+k>=n&&sa[i]+k>=n))) x[sa[i]]=p;
else x[sa[i]]=++p;
if(p+1>=n) break;
}
}
void Calc_ht()
{
for(int i=0; i<n; ++i) rk[sa[i]]=i;
ht[0]=0;
for(int k=0,p,i=0; i<n; ++i)//ht[rk[i]]>=ht[rk[i-1]]-1
{
if(!rk[i]) continue;//排名为0的 ht[rk[i]]=ht[0]=0
if(k) --k;
p=sa[rk[i]-1];
while(i+k<n&&p+k<n&&s[i+k]==s[p+k]) ++k;
ht[rk[i]]=k;
}
} int main()
{
scanf("%s",s), n=strlen(s);
Get_SA();
for(int i=0; i<n; ++i) printf("%d ",sa[i]+1);
putchar('\n'), Calc_ht();
for(int i=1; i<n; ++i) printf("%d ",ht[i]); return 0;
}

UOJ.35.[模板]后缀排序(后缀数组 倍增)的更多相关文章

  1. UOJ #35. 后缀排序 后缀数组 模板

    http://uoj.ac/problem/35 模板题,重新理了一遍关系.看注释吧.充分理解了倍增的意义,翻倍之后对上一次排序的利用是通过一种类似于队列的方式完成的. #include<ios ...

  2. UOJ #35. 后缀排序[后缀数组详细整理]

    #35. 后缀排序 统计 描述 提交 自定义测试 这是一道模板题. 读入一个长度为 nn 的由小写英文字母组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符 ...

  3. 洛谷.3809.[模板]后缀排序(后缀数组 倍增) & 学习笔记

    题目链接 //输出ht见UOJ.35 #include<cstdio> #include<cstring> #include<algorithm> const in ...

  4. Uoj #35. 后缀排序(后缀数组)

    35. 后缀排序 统计 描述 提交 自定义测试 这是一道模板题. 读入一个长度为 nn 的由小写英文字母组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符在 ...

  5. Codevs 1500 后缀排序(后缀数组)

    1500 后缀排序 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 天凯是MIT的新生.Prof. HandsomeG给了他一个 ...

  6. 【UOJ #35】后缀排序 后缀数组模板

    http://uoj.ac/problem/35 以前做后缀数组的题直接粘模板...现在重新写一下模板 注意用来基数排序的数组一定要开到N. #include<cstdio> #inclu ...

  7. [UOJ#35] [UOJ后缀数组模板题] 后缀排序 [后缀数组模板]

    后缀数组,解决字符串问题的有利工具,本题代码为倍增SA算法 具体解释详见2009年国家集训队论文 #include <iostream> #include <algorithm> ...

  8. Luogu P3809 【模板】后缀排序(后缀数组板题)

    忘完了- emmm-

  9. luogu3809 后缀排序 后缀数组

    ref and 挑战程序设计竞赛. 主要是发现自己以前写得代码太难看而且忘光了,而且我字符串死活学不会啊,kmp这种东西我都觉得是省选+难度啊QAQ #include <iostream> ...

随机推荐

  1. java web----TCP/DUP 通信

    服务端和单客户端通信 注意事项:如果服务端或者客户端采用read() 一个字节这种读取数据,只要另一方没有关闭连接,read是永远读取不到-1,会陷入死循环中: 解决方法:加上一个判断,程序员自己跳出 ...

  2. bzoj 4816

    这题是莫比乌斯反演的典型题也是很有趣的题. 题意:求,其中f为为斐波那契数列 那么首先观察一下指数,发现是我们熟悉的形式,可以转化成这样的形式: 令T=kd,且假设n<m,有: 令 则原式= 这 ...

  3. python接收邮件

    # -*- coding: utf-8 -*- import poplib import email from email.parser import Parser from email.header ...

  4. linux的systemctl服务及其使用

    一.systemd 系统初始化程序,系统开始的第一个进程,PID为1 二.systemctl命令 systemctl list-units    ##列出当前系统服务的状态 systemctl lis ...

  5. ServerSocket实现超简单HTTP服务器

    1.相关知识简介 HTTP协议 HTTP是常用的应用层协议之一,是面向文本的协议.HTTP报文传输基于TCP协议,TCP协议包含头部与数据部分,而HTTP则是包含在TCP协议的数据部分,如下图 HTT ...

  6. Tomcat延迟启动

    import subprocess as t import time, os, requests, sys WEB_IP = '127.0.0.1:8080' # WEB_IP = '127.0.0. ...

  7. web页在微信中访问增加遮罩层 右上角弹出在浏览器中打开

    https://blog.csdn.net/zgsdzczh/article/details/79744838 web页在微信中访问增加遮罩层 右上角弹出在浏览器中打开   <style typ ...

  8. 关于The specified Android SDK Build Tools version (26.0.2) is ignored, as it is below the minimum...

    今天将项目迁移到另一台笔记本,进行build出现以下问题,导致build失败 The specified Android SDK Build Tools version (26.0.2) is ign ...

  9. 在启用了“编辑并继续”时,修改包含 lambda 表达式的“method”将会阻止调试会话继续进行

    将所有的引用的“复制到本地”属性都设置成false就可以了

  10. Flink--sink到kafka

    package com.flink.DataStream import java.util.Properties import org.apache.flink.api.common.serializ ...