SA 后缀数组
SA 后缀数组
首先一定要确定\(SA\)是个什么东西
\(SA[i]\)表示的是排名为\(i\)的后缀是哪一个
至于后缀\(i\)的排名是多少,那个是\(rank[i]\)
当然啦
最最最难懂的就是基数排序
要是不用基数排序,每次对于一个二元组直接\(sort\)一下
这样的复杂度是\(O(nlog^2)\)
对于二元组的基数排序应该是这样做的:
首先把所有元素按照最后一维丢到依次对应的桶里面
然后顺次取出
再按照第一维依次丢入
再顺次取出
这样就可以排序啦
先把代码丢出来
bool cmp(int i,int j,int k){return y[i]==y[j]&&y[i+k]==y[j+k];}
void GetSA()
{
int m=30;
for(int i=1;i<=n;++i)t[x[i]=a[i]]++;
for(int i=1;i<=m;++i)t[i]+=t[i-1];
for(int i=n;i>=1;--i)SA[t[x[i]]--]=i;
for(int k=1;k<=n;k<<=1)
{
int p=0;
for(int i=0;i<=m;++i)y[i]=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)t[i]=0;
for(int i=1;i<=n;++i)t[x[y[i]]]++;
for(int i=1;i<=m;++i)t[i]+=t[i-1];
for(int i=n;i>=1;--i)SA[t[x[y[i]]]--]=y[i];
swap(x,y);
x[SA[1]]=p=1;
for(int i=2;i<=n;++i)x[SA[i]]=cmp(SA[i],SA[i-1],k)?p:++p;
if(p>=n)break;
m=p;
}
}
首先,第一次做\(k=0\)时
相当于每个后缀的第二维都是一样的
所以,直接按照第一维(也就是自己的值)
进行一次基数排序
接下来
每次基数排序都要利用到上一次的值
还记得吧,基数排序是先按照第二维从小往大拍
那么,我们就先把第二维的顺序搞出来
首先最小的一定就是没有第二维的东西
所以我们先把这些数直接丢进数组里面
接下来就是有第二维的东西啦
第\(i\)位的第二维是啥?\(rank[i+k]\)
所以,从小到达枚举\(SA\),这样保证第二维从小往大
那么,只要\(SA[i]>k\)
就证明它是一个东西的第二维
所以,把\(SA[i]-k\)丢到数组里面去就好啦
这样的话,按照第二维就拍好啦
再来依次按照第一维丢到桶里面去
做一遍基数排序就好啦
这样就能够求出\(SA\)啦
看起来很简单诶。。
只是数组不要搞混了
一定搞清楚每个数组是干啥的
比如我的代码
\(SA\)是后缀数组,\(SA[i]\)表示排名为\(i\)的串是哪一个
\(rank\)相当于排名,\(rank[i]\)表示第\(i\)个串的排名
\(x,y\)两个数组是记录顺序的
分别记录第一维和第二维的排序的顺序
\(t\)是桶
这样我们就很愉快的求出了\(SA\)
还有一个数组\(Height\)
\(Height[i]\)表示串\(SA[i]\)与\(SA[i-1]\)的最长公共前缀的长度
比如说,现在要求后缀\(i\)与\(j\)的最长公共前缀
那就只需要求\(min(Height[i]),i \in [rank[i]+1,rank[j]]\)
因为已经按照字典序排好序啦
\(Height\)显然可以暴力求
但是太不优美
我们有\(Height[rank[i]]>=Height[rank[i-1]]-1\)
证明(来自\(hihoCoder\))
设\(suffix(k)\)是排在\(suffix(i-1)\)前一名的后缀,
则它们的最长公共前缀是\(height[rank[i-1]]\)
那么\(suffix(k+1)\)将排在\(suffix(i)\)的前面(这里要求\(height[rank[i-1]]>1\),如果\(height[rank[i-1]]≤1\),原式显然成立)
并且\(suffix(k+1)\)和\(suffix(i)\)的最长公共前缀是\(height[rank[i-1]]-1\),
所以\(suffix(i)\)和在它前一名的后缀的最长公共前缀至少是\(height[rank[i-1]]-1\)
那么,我们按照\(rank\)的顺序来求\(Height\)就行啦
for(int i=1;i<=n;++i)Rank[SA[i]]=i;
for(int i=1,j=0;i<=n;++i)
{
if(j)j--;
while(a[i+j]==a[SA[Rank[i]-1]+j])++j;
height[Rank[i]]=j;
}
我现在也不是很熟
以后多做点题我再接着补
SA 后缀数组的更多相关文章
- Maximum repetition substring(POJ - 3693)(sa(后缀数组)+st表)
The repetition number of a string is defined as the maximum number \(R\) such that the string can be ...
- Distinct Substrings(spoj694)(sam(后缀自动机)||sa(后缀数组))
Given a string, we need to find the total number of its distinct substrings. Input \(T-\) number of ...
- 【后缀数组之SA数组】【真难懂啊】
基本上一搜后缀数组网上的模板都是<后缀数组——处理字符串的有力工具>这一篇的注释,O(nlogn)的复杂度确实很强大,但对于初次接触(比如窝)的人来说理解起来也着实有些困难(比如窝就活活好 ...
- 关于后缀数组的倍增算法和height数组
自己看着大牛的论文学了一下后缀数组,看了好久好久,想了好久好久才懂了一点点皮毛TAT 然后就去刷传说中的后缀数组神题,poj3693是进化版的,需要那个相同情况下字典序最小,搞这个搞了超久的说. 先简 ...
- Long Long Message(后缀数组)
Long Long Message Time Limit: 4000MS Memory Limit: 131072K Total Submissions: 30427 Accepted: 12 ...
- Java后缀数组-求sa数组
后缀数组的一些基本概念请自行百度,简单来说后缀数组就是一个字符串所有后缀大小排序后的一个集合,然后我们根据后缀数组的一些性质就可以实现各种需求. public class MySuffixArrayT ...
- bzoj3796(后缀数组)(SA四连)
bzoj3796Mushroom追妹纸 题目描述 Mushroom最近看上了一个漂亮妹纸.他选择一种非常经典的手段来表达自己的心意——写情书.考虑到自己的表达能力,Mushroom决定不手写情书.他从 ...
- [笔记]后缀数组SA
参考资料这次是真抄的: 1.后缀数组详解 2.后缀数组-学习笔记 3.后缀数组--处理字符串的有力工具 定义 \(SA\)排名为\(i\)的后缀的位置 \(rk\)位置为\(i\)的后缀的排名 \(t ...
- 后缀数组(SA)总结
后缀数组(SA)总结 这个东西鸽了好久了,今天补一下 概念 后缀数组\(SA\)是什么东西? 它是记录一个字符串每个后缀的字典序的数组 \(sa[i]\):表示排名为\(i\)的后缀是哪一个. \(r ...
随机推荐
- 获取网站证书的两种方法(wireshark or firefox nightly)
一.使用Wireshark 截取数据包的方式 1. wireshark软件需要使用管理员权限运行,开始捕获后,按下ctrl + f,查找证书所在分组,从source 和destination 栏可以看 ...
- GitHub入门与实践
基本命令 git status 工作区状态 git add git commint 暂存区 git push gitHub客户端 下载网址:https://desktop.github.com/ 解决 ...
- 4、flask之分页插件的使用、添加后保留原url搜索条件、单例模式
本篇导航: flask实现分页 添加后保留原url搜索条件 单例模式 一.flask实现分页 1.django项目中写过的分页组件 from urllib.parse import urlencode ...
- 你所有不知的margin属性
前言 致谢 本文总结于 张鑫旭老师的 CSS深入理解之margin课程,感谢张老师的辛苦付出! 难学的 CSS 作为前端狗的我们,每天都要和网页打交道.当 UI 将设计稿发给你时,CSS 的知识便显得 ...
- 可拖动布局之Gridster
看过bootstrap可视化布局系统的人是不是都会对页面元素的拖拽有着很大的兴趣?下面呢,楼主就给大家讲两个楼主知道的拖拽小插件吧. 一.gridster 1.了解gridster 后续官网:http ...
- mongodb的TTL索引介绍(超时索引)
TTL索引是mongodb新支持的用于延时自动删除记录的一种索引.它仅包含一个字段,该字段值需要是Date()类型,并且不支持复合索引.可以指定某条记录在延时固定时间后自动删除.数据自动超时删除主要用 ...
- Oracle中的多表查询(笛卡尔积原理)
本次预计讲解的知识点 1. 多表查询的操作.限制.笛卡尔积的问题: 2. 统计函数及分组统计的操作: 3. 子查询的操作,并且结合限定查询.数据排序.多表查询.统计查询一起完成各个复杂查询的操作: 一 ...
- java中的Collection集合类
随着1998年JDK 1.2的发布,同时新增了常用的Collections集合类,包含了Collection和Map接口.而Dictionary类是在1996年JDK 1.0发布时就已经有了.它们都可 ...
- 深入研究Node.js的底层原理和高级使用
深入研究Node.js的底层原理和高级使用
- Java爬虫----有道翻译初步
目标:http://fanyi.youdao.com/ 用爬虫实现翻译功能. 利用f12查看网页Network,可以发现 有关翻译的表单请求通过 http://fanyi.youdao.com/tr ...