首页 > 其他分享 >浅谈后缀数组

浅谈后缀数组

时间:2023-09-01 22:13:11浏览次数:43  
标签:log 后缀 时间 数组 sa rk 浅谈

编写中,待完善。。。

前置知识 : 后缀(???),基数排序(说通俗一点就是桶子排序),基础倍增。

后缀数组是一种处理字符串问题的利器,可以起到代替后缀树的作用,在码量上具有绝对的优势。正常情况下,大家都会使用后缀数组而非后缀树。虽然后缀数组十分的好写,但是过程难以令人理解。今天我会使用尽量通俗的语言帮助大家理解什么是后缀数组,以及相关的拓展。

在开始之前

我们需要对于一些变量进行定义(别的数字在后边讲到):

\(sa_i\) 表示排名为 \(i\) 的后缀下标是多少。

\(rk_i\) 表示下标 \(i\) 的后缀的排名是多少。

那么这两个数组是具有性质: \(sa[rk_i]=rk[sa_i]=i\) 。这一点看起来比较的绕,但是还是稍加思考可以理解的。也就是说,我们知道了 \(sa\) 和 \(rk\) 中的一者,就可以在线性的时间内推出另一个。

后缀排序

现在进行了定义,该如何求出这个后缀数组呢?我们讲如下两种方法(最最最最牛逼但是常数和码量极大的 \(\text{DC3}\) 我们暂不讨论):

字符串哈希算法

这个算法的时间复杂度是 \(O(n \log^2 n)\) 。因为相比其他解法较劣势的时间复杂度,并不是很常使用。

相比大家知道怎么编写 \(std::sort\) 的自定义比较函数吧。如果这个比较的时间是 \(O(T)\) 的,那么我们的排序时间就可以做到 \(O(Tn \log n)\) 。那么现在我们的目标就是在尽量块的时间内比较两个后缀的字典序。

最简单的做法就是暴力的枚举,但是注意到 \(LCP\) (最长公共前缀) 是可以二分的,所以我们可以去二分第一个不一样的前缀,比较最后一个字符的大小就可以了。问题就又变换为了如何去比较两个字符串相同,这个显然使用字符串哈希可以在 \(O(1)\) 的时间内解决。那么我们的比较时间就从 \(O(n)\) 优化到了 \(O(n\log n)\) 。

最终的时间复杂度就是 \(O(n \log^2 n)\) 。

代码

标签:log,后缀,时间,数组,sa,rk,浅谈
From: https://www.cnblogs.com/Diavolo/p/17672933.html

相关文章

  • 后缀数组
    后缀数组前情回顾:KMP&AC自动机马拉车&回文自动机在写后缀自动机之前先写一个小清新的后缀相关算法,也就是后缀排序。后缀数组记录的就是排序之后的这个序,具体来说有三个重要的数组。现在有一个字符串\(s\),为了方便记\(s\)的长度为\(N\)。\(s_i\)表示\(s\)这个字符串的......
  • JavaScript—数组
    数组的概念数组是指一组数据的集合,其中的每一个数据称作元素在数组中可以存放任意类型的元素。数组是一种将一组数据存储在单个变量名下的方式。创建数组创建数组vararr=newArray();//使用new创建一个空数组vararr0=[];//利用数组字面量创建数组vara......
  • 2023-09-01:用go语言编写。给出两个长度均为n的数组, A = { a1, a2, ... ,an }, B = { b1
    2023-09-01:用go语言编写。给出两个长度均为n的数组,A={a1,a2,...,an},B={b1,b2,...,bn}。你需要求出其有多少个区间[L,R]满足:数组A中下标在[L,R]中的元素之和在[La,Ra]之中,数组B中下标在[L,R]中的元素之和在[Lb,Rb]之中。输入:第一行有一个正整数N(1<=N<=100000),代表两......
  • 2023-09-01:用go语言编写。给出两个长度均为n的数组, A = { a1, a2, ... ,an }, B = { b1
    2023-09-01:用go语言编写。给出两个长度均为n的数组,A={a1,a2,...,an},B={b1,b2,...,bn}。你需要求出其有多少个区间[L,R]满足:数组A中下标在[L,R]中的元素之和在[La,Ra]之中,数组B中下标在[L,R]中的元素之和在[Lb,Rb]之中。输入:第一行有一个正整数N(1<=N<=10000......
  • 关于处理 vue data中对象或数组中响应式数据的注意点
    vue2中针对对象中的响应式数据,如果要想修改他们,只能通过监听的特性实现。不能直接赋值。在vue2源码中,计算属性和watch的实现方式是一样的,都具有监听响应式对象或数组中的数据的功能。区别就是,计算属性具有缓存机制。除此之外,还可以直接使用this.$set(obj,key:String,value......
  • Java:commons-codec实现byte数组和16进制字符串转换
    (目录)commons-codec文档https://commons.apache.org/proper/commons-codec/https://mvnrepository.com/artifact/commons-codec/commons-codec坐标<dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifact......
  • Python-嵌套数组获取对应的值
    二维数组示例:er_array=[['霹雳火','急先锋','超音速']]forinner_arrayiner_array:#嵌套二维数组,使用两个嵌套的for循环遍历数组并获取值forvalueininner_array:print(value) 方法一:使用enumerate函数,遍历获取元素的索引er_array=[['霹雳......
  • Python中如何快速解析JSON对象数组
    由于浏览器可以迅速地解析JSON对象,它们有助于在客户端和服务器之间传输数据。本文将描述如何使用Python的JSON模块来传输和接收JSON数据。JavaScriptObjectNotationJSON(JavaScriptObjectNotation)是一种用于数据交换的语法,它对人的读写很简单,对计算机的解析和生产也很简单......
  • 动态数组指针应用
    TypeTMyArr=arrayofarrayofarrayofInteger;Pint=^TMyArr;varPArr:Pint;i,j,k,ic,jc,kc:Integer;beginic:=2;jc:=3;kc:=4;New(PArr);SetLength(PArr^,ic,jc,kc);fori:=0toic-1doforj:=0tojc-1......
  • 数组类型指针
    {使用一个元素的数组指针}PMyRec=^TMyRec;TMyRec=recordF1:Char;F2:Word;end;procedureTForm1.Button1Click(Sender:TObject);typePArr=^TArr;TArr=array[0..0]ofTMyRec;varbuf:PArr;i:Integer;beginGetMem(buf,SizeOf......