这篇博客不打算讲多么详细,网上关于后缀数组的blog比我讲的好多了,这一篇博客我是为自己加深印象写的。

给你们分享了那么多,容我自私一回吧~

参考资料:这位dalao的blog

一、关于求SuffixArray的一些变量定义:

1. sa[i]=j,表示第i名的后缀从j开始

**存的是下标**

2. rnk[i]=j,从i开始的后缀是第j名的

**与sa为互逆运算,存的是值**

3. tp[i]=j, 第二关键字为i的后缀从j开始

**可理解为第二关键字的SA,存的是下标**

插入解释一下第一关键字和第二关键字:

我们要对所有的后缀进行排序,怎么排呢?

开始时,我们每个字符的后缀存的只有它自己,所以它后缀的大小就是它的ASCII码。

我们把每个字符i看成(s[i],i)的二元组,如果我们直接丢pair<int,int>里面然后std::sort,

这样的时间复杂度是O(log^2 n)的,显然不够优秀。

所以就需要用到基数排序RadixSort,不了解的自行百度。

再使用倍增法,就可以使我们排序的时间复杂度降低到O(logn)。

所以我们要对每个后缀的前两个字母进行排序,第一个字母的相对关系已经得到了。

第i个后缀的第二个字母,就是第i+1个后缀的第一个字母,利用这个关系我们第二个字母的相对关系也就知道了。

我们的tp数组就是用来记录它的,rnk[i]表示上一轮中第i个后缀的排名。

这里引用神仙attack的一句话,我觉得讲的非常到位:

对于一个长度为w的后缀,你可以形象的理解为:

第一关键字针对前w2个字符形成的字符串,第二关键字针对后w2个字符形成的字符串

然后对每个后缀的前4个字母组成的字符串排序,前8个,前16个...这就是倍增法求SA的流程了。

给出RadixSort的代码:

void RadixSort(int a[],int b[]){//基数排序
for(int i=;i<=m;i++)tax[i]=;
for(int i=;i<=n;i++)tax[a[i]]++;
for(int i=;i<=m;i++)tax[i]+=tax[i-];
for(int i=n;i>=;i--)sa[tax[a[b[i]]]--]=b[i];
}

实在不能理解RadixSort也没有关系,代码很短

再给出求SA的代码:

bool cmp(int *r,int a,int b,int k){
return r[a]==r[b]&&r[a+k]==r[b+k];
}
void getSA(int a[],int b[]){
for(int i=;i<=n;i++)
m=max(m,a[i]=s[i]-''),b[i]=i;
RadixSort(a,b);
for(int p=,j=;p<n;j<<=,m=p){
p=;
for(int i=;i<=j;i++)b[++p]=n-j+i;
for(int i=;i<=n;i++)if(sa[i]>j)b[++p]=sa[i]-j;
RadixSort(a,b);
int *t=a;a=b;b=t;
a[sa[]]=p=;
for(int i=;i<=n;i++)
a[sa[i]]=cmp(b,sa[i],sa[i-],j)?p:++p;
}
}

关于代码的解释,有时间再填坑。本蒟蒻要学的算法还很多...SA就粗略地理解一下好了

开始填坑,先补充一个东西叫height数组。

height[i]表示排名为i的后缀和排名为i-1的后缀的最长公共前缀LCP。

暴力求解时间复杂度是O(n^2),根据一个性质height[i+1]>=height[i]-1

可以O(n)时间内求出height数组,具体代码:

void getHeight(){
for(int i=,j=;i<=n;i++){
if(j)j--;
while(s[i+j]==s[sa[rnk[i]-]+j])j++;
height[rnk[i]]=j;
}
}

关于这个height数组,它可以干什么,给出一张列表:

两个后缀的最大公共前缀

lcp(x,y)=min(heigh[x−y])lcp(x,y)=min(heigh[x−y]), 用rmq维护,O(1)查询

可重叠最长重复子串

height数组里的最大值

不可重叠最长重复子串

首先二分答案x,对height数组进行分组,保证每一组的最小height都>=x

依次枚举每一组,记录下最大和最小长度,若sa[max]−sa[min]>=x那么可以更新答案

本质不同的子串的数量

枚举每一个后缀,第i个后缀对答案的贡献为len−sa[i]+1−height[i]

浅谈后缀数组SA的更多相关文章

  1. 后缀数组(SA)总结

    后缀数组(SA)总结 这个东西鸽了好久了,今天补一下 概念 后缀数组\(SA\)是什么东西? 它是记录一个字符串每个后缀的字典序的数组 \(sa[i]\):表示排名为\(i\)的后缀是哪一个. \(r ...

  2. 后缀数组SA学习笔记

    什么是后缀数组 后缀数组\(sa[i]\)表示字符串中字典序排名为\(i\)的后缀位置 \(rk[i]\)表示字符串中第\(i\)个后缀的字典序排名 举个例子: ababa a b a b a rk: ...

  3. 后缀数组SA入门(史上最晦涩难懂的讲解)

    参考资料:victorique的博客(有一点锅无伤大雅,记得看评论区),$wzz$ 课件(快去$ftp$%%%),$oi-wiki$以及某个人的帮助(万分感谢!) 首先还是要说一句:我不知道为什么我这 ...

  4. bzoj3796(后缀数组)(SA四连)

    bzoj3796Mushroom追妹纸 题目描述 Mushroom最近看上了一个漂亮妹纸.他选择一种非常经典的手段来表达自己的心意——写情书.考虑到自己的表达能力,Mushroom决定不手写情书.他从 ...

  5. [笔记]后缀数组SA

    参考资料这次是真抄的: 1.后缀数组详解 2.后缀数组-学习笔记 3.后缀数组--处理字符串的有力工具 定义 \(SA\)排名为\(i\)的后缀的位置 \(rk\)位置为\(i\)的后缀的排名 \(t ...

  6. 【字符串】后缀数组SA

    后缀数组 概念 实际上就是将一个字符串的所有后缀按照字典序排序 得到了两个数组 \(sa[i]\) 和 \(rk[i]\),其中 \(sa[i]\) 表示排名为 i 的后缀,\(rk[i]\) 表示后 ...

  7. 后缀数组SA

    复杂度:O(nlogn) 注:从0到n-1 const int maxn=1e5; char s[maxn]; int sa[maxn],Rank[maxn],height[maxn],rmq[max ...

  8. 洛谷2408不同字串个数/SPOJ 694/705 (后缀数组SA)

    真是一个三倍经验好题啊. 我们来观察这个题目,首先如果直接整体计算,怕是不太好计算. 首先,我们可以将每个子串都看成一个后缀的的前缀.那我们就可以考虑一个一个后缀来计算了. 为了方便起见,我们选择按照 ...

  9. 洛谷4248 AHOI2013差异 (后缀数组SA+单调栈)

    补博客! 首先我们观察题目中给的那个求\(ans\)的方法,其实前两项没什么用处,直接\(for\)一遍就求得了 for (int i=1;i<=n;i++) ans=ans+i*(n-1); ...

随机推荐

  1. Apache Flink - 基本API概念

    Flink程序是实现分布式集合转换的常规程序.集合最初是从源创建的.通过接收器(slink)返回结果,接收器可以将数据写到某个文件或stdout.Flink可以在各种环境(context)中运行,本地 ...

  2. the requested PHP extension dom is missing from your system

    composer  出错 the requested PHP extension dom is missing from your system 解决办法    yum install  php70w ...

  3. python操作MySQL数据库的三个模块

    python使用MySQL主要有两个模块,pymysql(MySQLdb)和SQLAchemy. pymysql(MySQLdb)为原生模块,直接执行sql语句,其中pymysql模块支持python ...

  4. linux下什么工具可以用来纠正文件中的拼写和排版错误?

    答: ispell,官网在此

  5. Swift 基本语法

    如果创建的是 OS X playground 需要引入 Cocoa : import Cocoa /* 我的第一个 Swift 程序 */ var myString = "Hello, Wo ...

  6. Eclipse项目修改编译jdk版本(Failed to read candidate component class: file 处理)

    转: Failed to read candidate component class: file 处理 2018年03月09日 07:15:54 爱萨萨 阅读数 10041   出错现象: org. ...

  7. 高级java面试宝典

    1.spring事物的配置 spring事物分为俩种,一种是注解事物,一种是AOP事物注解事物的配置: 事物的隔离级别,事物的传播性,事物的超时回滚,哪些异常回滚,哪些不回滚,有默认的回滚规则注解事物 ...

  8. Hystrix-基本概念(设计原则和两种隔离技术)

    一.Hystrix是什么在微服务的架构系统中,每个服务都可能会调用很多其他服务,被调用的那些服务就是依赖服务.有的时候某些依赖服务出现故障也是很正常的.Hystrix可以让我们在对服务间的调用进行控制 ...

  9. JAVA 基础编程练习题34 【程序 34 三个数排序】

    34 [程序 34 三个数排序] 题目:输入 3 个数 a,b,c,按大小顺序输出. 程序分析:利用指针方法. package cskaoyan; public class cskaoyan34 { ...

  10. ”Unstanding the Bias-Variance Tradeoff“主题内容翻译

    对预测模型讨论,预测误差(error)分两类:偏差(bias)造成的误差与方差(variance)造成的误差.最小化偏差与方差的一个权衡.理解这两类误差有利于诊断模型结果和避免过拟合和欠拟合. 偏差与 ...