题目链接

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

后缀数组

下标从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. 右键菜单添加打开CMD选项

    转载: https://www.cnblogs.com/mkdd/p/8649139.html#undefined 目前用的win7sp1系统,平时打开CMD窗口通常用三种方法:1.win+R然后输入 ...

  2. OrCAD Capture CIS 16.6 在原理图页面内放置图片

    OrCAD Capture CIS 16.6 菜单:Place > Picture... 在Place Picture窗口中,文件类型选择All Files (*.*),接着选择需要插入的图片, ...

  3. 安装Mycat 曾经踩的那些坑

    1. INFO | jvm | ----/--/-- --:--:-- | Caused by: io.mycat.config.util.ConfigException: schema TEST d ...

  4. Redis 学习手册

    一:Redis的简介 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,和Memcached类似,它支持存储的value类型相对更多,包 ...

  5. Linux环境安装Eclipse工具开发

    1.官网下载maven:https://maven.apache.org/download.cgi 2.上传到虚拟机进行解压缩操作: [hadoop@slaver1 package]$ tar -zx ...

  6. kickstart-E

    A题 简答模拟题 #include <iostream> #include<stdio.h> #include <set> #include <algorit ...

  7. 构建ASP.NET MVC5+EF6+EasyUI 1.4.3+Unity4.x注入的后台管理系统(66)-MVC WebApi 用户验证 (2)

    前言: 构建ASP.NET MVC5+EF6+EasyUI 1.4.3+Unity4.x注入的后台管理系统(65)-MVC WebApi 用户验证 (1) 回顾上一节,我们利用webapi简单的登录并 ...

  8. GGTalk ——C#开源即时通讯系统

    http://www.cnblogs.com/justnow/ GGTalk ——C#开源即时通讯系统 下载中心   GGTalk(简称GG)是可在广域网部署运行的QQ高仿版,2013.8.7发布GG ...

  9. 10个财务工作中常用的 Excel 万能公式

    1.多条件判断公式 =IF(AND(条件1,条件2...条件n),同时满足条件返回的值,不满足条件返回的值) =IF(OR(条件1,条件2...条件n),同时满足任一条件返回的值,不满足条件返回的值) ...

  10. hibnet 自动生成表格

    在pom文件中添加相关的依赖 在application.yml文件中添加配置信息 新建实体类Boy 项目运行,mysql就产生了一个boy表. 需要注意的是:当配置文件ddl-auto: create ...