UOJ.35.[模板]后缀排序(后缀数组 倍增)
论找到一个好的教程的正确性。。
后缀数组
下标从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.[模板]后缀排序(后缀数组 倍增)的更多相关文章
- UOJ #35. 后缀排序 后缀数组 模板
http://uoj.ac/problem/35 模板题,重新理了一遍关系.看注释吧.充分理解了倍增的意义,翻倍之后对上一次排序的利用是通过一种类似于队列的方式完成的. #include<ios ...
- UOJ #35. 后缀排序[后缀数组详细整理]
#35. 后缀排序 统计 描述 提交 自定义测试 这是一道模板题. 读入一个长度为 nn 的由小写英文字母组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符 ...
- 洛谷.3809.[模板]后缀排序(后缀数组 倍增) & 学习笔记
题目链接 //输出ht见UOJ.35 #include<cstdio> #include<cstring> #include<algorithm> const in ...
- Uoj #35. 后缀排序(后缀数组)
35. 后缀排序 统计 描述 提交 自定义测试 这是一道模板题. 读入一个长度为 nn 的由小写英文字母组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符在 ...
- Codevs 1500 后缀排序(后缀数组)
1500 后缀排序 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 天凯是MIT的新生.Prof. HandsomeG给了他一个 ...
- 【UOJ #35】后缀排序 后缀数组模板
http://uoj.ac/problem/35 以前做后缀数组的题直接粘模板...现在重新写一下模板 注意用来基数排序的数组一定要开到N. #include<cstdio> #inclu ...
- [UOJ#35] [UOJ后缀数组模板题] 后缀排序 [后缀数组模板]
后缀数组,解决字符串问题的有利工具,本题代码为倍增SA算法 具体解释详见2009年国家集训队论文 #include <iostream> #include <algorithm> ...
- Luogu P3809 【模板】后缀排序(后缀数组板题)
忘完了- emmm-
- luogu3809 后缀排序 后缀数组
ref and 挑战程序设计竞赛. 主要是发现自己以前写得代码太难看而且忘光了,而且我字符串死活学不会啊,kmp这种东西我都觉得是省选+难度啊QAQ #include <iostream> ...
随机推荐
- java----AOP框架理解
面向切面编程: 通过动态代理+加配置文件 目的解耦 给主逻辑添加一些修饰功能,但是不在主逻辑代码中进行修改,有点类似python中的装饰器,调用方法还是是通过接口的那个类来调用: import jav ...
- ps和AI使用过程中的易错点整理
ps:1.视图工具:1)标尺2)参考线3)网格:视图-->--显示>-->网格4)修改网格:编辑-->首选项>-->参考线.网格和切片 5)放大工具:画布中单击可放 ...
- ajax beforeSend 写的显示隐藏代码不执行
ajax如果要写像下方格式 $.ajax({ url: ajaxurl, type: 'POST', dataType: 'json', async:true, data: { }, beforeSe ...
- 目标检测之选择性搜索-Selective Search
一.滑动窗口检测器 一种用于目标检测的暴力方法就是从左到右,从上到下滑动窗口,利用分类识别目标.为了在不同观察距离处检测不同的目标类型,我们可以使用不同大小和宽高比的窗口 得到窗口内的图片送入分类器, ...
- k-近邻算法-优化约会网站的配对效果
KNN原理 1. 假设有一个带有标签的样本数据集(训练样本集),其中包含每条数据与所属分类的对应关系. 2. 输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较. a. 计算新 ...
- HTML文本格式化与HTML 超链接
文本格式化<b>加粗文本</b><i>斜体文本</i><code>电脑自动输出</code><sub> 下标< ...
- [转]MyEclipse 2015优化技巧
http://www.chinahadoop.cn/group/16/thread/1660 http://www.bkjia.com/Javabc/1077158.html 只有不断的学习才能使人充 ...
- 1个汉字在UTF-8编码占3个字节
http://blog.csdn.net/ns_code/article/details/14162087 http://www.ruanyifeng.com/blog/2007/10/ascii_u ...
- WPF: Hide grid row
http://stackoverflow.com/questions/2502178/wpf-hide-grid-row Setting all the Items in the Row to Vis ...
- ionic2程序调试
新手一枚,之前一直做.net开发,最近接触Ionic2,也没有人带,只能自己一点点抠文档,查资料.一直苦于无法直接调试打包发不好的app,只能在代码里面加上alert一点一点的抛出要看信息,感觉就像瞎 ...