后缀数组

后缀数组(suffix array)

*爱你&永不变心* 提交于 2020-02-03 00:13:23
参考: Suffix array - Wiki 后缀数组(suffix array)详解 6.3 Suffix Arrays - 算法红宝书 Suffix Array 后缀数组 基本概念 应用 :字符串处理、生物信息序列处理 后缀 :学过英语的都知道什么叫后缀,就是从某个位置开始到字符串结尾的特殊子串,记住 Suffix(i)=S[i...len(S)-1],i就是后缀起始位置 后缀数组 :就是将后缀排序好后放到一个一维数组里,SA[i]存放排名第i大的后缀首字符下标,并且保证 Suffix(SA[i])<Suffix(SA[i+1]), 1<=i<n 。 Rank数组 :rank[i]存放suffix(i)的优先级 注:后缀数组和Rank数组为互逆运算。我们只要算出了sa数组,就可以在O(n)的时间复杂度内算出rank数组。 height数组 :height[i]保存的是suffix(i)和suffix(i-1)的最长公共前缀的长度。也就是排名相邻的两个后缀的 最长公共前缀 。 看图说话: 下面列出了aabaaaab的所有后缀,并对其标号1..8 构造Rank数组,对每个i一次计算其后缀的排名,如下第一个后缀排名第4,所以Rank数组第一个为4 怎么构造后缀数组 构造sa数组 构造rank数组 构造height数组 例子 aabaaaab 总共有n=8个后缀: 1:

KMP算法

早过忘川 提交于 2020-02-02 14:09:17
KMP算法 KMP算法用于在文本串S内查找模式串P的出现位置 时间复杂度为O(M + N) 最大长度表 前缀和后缀 前缀:除了最后一个字符以外,一个字符串的全部头部组合 后缀:除了第一个字符以外,一个字符串的全部尾部集合 前缀后缀的最长公共元素长度 举例说明,假如模式串为 P = "ABCABD" 模式串 A B C A B D 最大前缀后缀公共元素长度 0 0 0 1 2 0 “A” :前缀为空集,后缀为空集,共有元素长度为0 “AB”:前缀为[A],后缀为[B],共有元素长度为0 “ABC”:前缀为[A, AB],后缀为[C, BC],共有长度为0 “ABCA”:前缀为[A, AB, ABC],后缀为[A, CA, BCA],共有长度为1 “ABCAB”:前缀为[A, AB, ABC, ABCA],后缀为[B, AB, CAB, BCAB],共有长度为2 “ABCABD”:前缀为[A, AB, ABC, ABCA, ABCAB],后缀为[D, BD, ABD, CABD, BCABD],共有长度为0 next数组 next数组是KMP算法的核心部分,其中 next[i] 的定义为: 在模板串P[0, i - 1]范围内的前缀后缀最长公共元素长度 根据定义可以知道next数组可以由最大长度表向右移动一位得到 为了计算方便 next[0] 通常设为 -1 示例 模板串 A B C

后缀数组LCP + 二分 - UVa 11107 Life Forms

南笙酒味 提交于 2020-02-01 03:51:56
Life Forms Problem's Link Mean: 给你n个串,让你找出出现次数大于n/2的最长公共子串。如果有多个,按字典序排列输出。 analyse: 经典题。 直接二分判断答案。 判断答案p时,我们扫一遍height数组,如果height[i]<p时开辟一个新段。 判断时用set存储所在串编号,不仅起到去重的作用,而且也起到统计段长的作用。 也可以直接用字符串hash来做,也是先二分,然后O(n)判断,时间复杂度和后缀数组一样。 Time complexity: O(N*logN) Source code: 1.后缀数组: /* * this code is made by crazyacking * Verdict: Accepted * Submission Date: 2015-09-05-14.44 * Time: 0MS * Memory: 137KB */ #include <queue> #include <cstdio> #include <set> #include <string> #include <stack> #include <cmath> #include <climits> #include <map> #include <cstdlib> #include <iostream> #include <vector> #include

[学习笔记] 后缀数组

假装没事ソ 提交于 2020-01-31 22:49:10
参考: https://www.cnblogs.com/zwfymqz/p/8413523.html 代码: /* * @Author: chenkexing * @Date: 2020-01-19 19:14:09 * @Last Modified by: chenkexing * @Last Modified time: 2020-01-31 22:12:27 */ // #pragma GCC optimize(2) // #pragma GCC optimize(3) // #pragma GCC optimize(4) #include <algorithm> #include <iterator> #include <iostream> #include <cstring> #include <cstdlib> #include <iomanip> #include <bitset> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <stack> #include <cmath> #include <queue> #include <list> #include <map> #include <set> #include <cassert> //

POJ1743 Musical Theme【后缀数组】

假装没事ソ 提交于 2020-01-25 08:48:27
题目描述: 长度为n(<=20000)的整数序列(数值范围1到88),求长度大于等于5且最长的两个不重叠子串,使得其中一个整体加上或减去一个数后与另一个完全相同。输出长度。 题目分析: 设原串为 a [ i ] a[i] a [ i ] ,令 b [ i ] = a [ i + 1 ] − a [ i ] b[i]=a[i+1]-a[i] b [ i ] = a [ i + 1 ] − a [ i ] , b [ l ] b[l] b [ l ] 到 b [ r ] b[r] b [ r ] 对应于原串的 a [ l ] a[l] a [ l ] 到 a [ r + 1 ] a[r+1] a [ r + 1 ] 偏移后相同 等价于 差分后的串完全相同。 注意差分后两个串需要间隔一个位置。 Code: # include <cstdio> # include <cstring> # include <algorithm> # define maxn 20005 using namespace std ; int b [ maxn ] , ary [ 4 ] [ maxn ] , h [ maxn ] ; int * sa = ary [ 0 ] , * rk = ary [ 1 ] , * nsa = ary [ 2 ] , * nrk = ary [ 3 ] ; void

POJ-3294 Life Forms (后缀数组)

╄→гoц情女王★ 提交于 2020-01-19 16:13:37
POJ-3294 Life Forms (后缀数组) 要按照字典序输出的话后缀自动机就比较麻烦了,所以没有 把所有字符串接在一起,中间用不同的奇怪的字符隔开 二分答案 \(x\) ,将 \(LCP\) 数组分组使得每组中的 \(LCP\ge x\) ,找一下是否一半的串都在这组中出现过了即可 输出注意格式 #include<cstdio> #include<algorithm> #include<iostream> #include<cctype> #include<cstring> #include<cassert> using namespace std; #define reg register #define pb push_back typedef long long ll; typedef unsigned long long ull; #define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i) #define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i) template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); } template <class T> inline void cmax

后缀数组&自动机&树

烈酒焚心 提交于 2020-01-19 13:59:33
后缀数组&自动机&树 后缀系列字符串结构总结 博主的一些习惯 字符串叫 \(S\) ,长度叫 \(n\) ,字符串 \(a,b\) 相接为 \(a+b\) ,下标从一开始, \(S_{i,j}\) 表示 \(i\) 到 \(j\) 这一段子串 字符串之间 \(<,>\) 表示字典序比较 所有例题的题解都可以在文末找到 \[ \ \] \[ \ \] 1: SA(后缀数组) 需要数组 \(rk[i]\) 表示第 \(i\) 个后缀的排名(不存在相同), \(sa[i]\) 表示排名为 \(i\) 的后缀编号,以及辅助数组 \(cnt,tmp\) 1-1 后缀排序 由于博主水平不够,所以没有去学习dc3( \(O(n)\) )算法,下文介绍的是da( \(O(n\log n)\) )算法 后缀排序,顾名思义就是要对于 \(S\) 的每个后缀 \(S_{i,n}\) (下称 \(Suf_i\) ),按照字典序排序,空字符的字典序最小 考虑用倍增+基数排序实现 对于当前已经确定的长度 \(k\) ,即 \(S_{i,i+k-1}\) (超出部分为空字符)的排序已经完成,接下来考虑对于 \(S_{i,i+2k-1}\) 的排序 \(S_{i,i+2k-1}=S_{i,i+k-1}+S_{i+k,i+2k-1}\) ,所以可以根据已经排序完的部分为值对于两部分使用基数排序合并得到 \(2k\)

字符串匹配——KMP算法

Deadly 提交于 2020-01-19 03:26:10
KMP算法 【*注】转载来源:[(https://www.cnblogs.com/SYCstudio/p/7194315.html)] 【膜拜原作者大大,文章转载,补充了字符串匹配的完整例子ο(=•ω<=)ρ⌒☆】 引入 首先我们来看一个例子,现在有两个字符串A和B,问你在A中是否有B,有几个?为了方便叙述,我们先给定两个字符串的值 A="abcaabababaa" B="abab" 那么普通的匹配是怎么操作的呢? 当然就是一位一位地比啦。(下面用蓝色表示已经匹配,黑色表示匹配失败) 但是我们发现这样匹配很 浪费! 为什么这么说呢,我们看到第4步: 在第4步的时候,我们发现第3位上c与a不匹配,然后第五步的时候我们把B串向后移一位,再从第一个开始匹配。 这里就有一个对已知信息很大的浪费,因为根据前面的匹配结果,我们知道B串的前两位是ab,所以不管怎么移,都是不能和b匹配的,所以应该直接跳过对A串第二位的匹配,对于A串的第三位也是同理。 或许这这个例子还不够经典,我们再举一个。 A="abbaabbbabaa" B="abbaaba" 在这个例子中,我们依然从第1位开始匹配,直到匹配失败: abbaab b babba abbaab a 我们发现第7位不匹配 那么我们若按照原来的方式继续匹配,则是把B串向后移一位,重新从第一个字符开始匹配 a b baabbbabba _ a

后缀数组初探

*爱你&永不变心* 提交于 2020-01-19 02:52:44
后缀数组 ​ 本文总结了后缀数组(Suffix Array,SA)的倍增算法以及如何在O(n)预处理、O(1)查询的时间复杂度内求得任意两个后缀的最长公共前缀(Longest Common Prefix,LCP)。 1 基本定义 后缀i (suffix[i]):从下标i起始的后缀。(特别地,认为字符串本身也是自己的后缀) 后缀数组 (Saffix Array,SA):将后缀0 \(\rightarrow\) N-1按字典序从小到大排列,SA[i]为第i (0 \(\rightarrow\) N-1)小后缀的起始位置。 名次数组 (Rank):将后缀0 \(\rightarrow\) N-1按字典序从小到大排列,Rank[ i (0 \(\rightarrow\) N-1)]为后缀i的名次。 高度数组 (Height):Height[i (0 \(\rightarrow\) N-1)]为suffix[ SA[i] ]和suffix[ SA[i-1] ]的最长公共前缀。(Height[0]没有意义) 辅助数组(H):H[ i (0 \(\rightarrow\) N-1) ]为Height[ Rank[i] ]。 2 基本性质 后缀数组与名次数组互逆:SA[ rank[i] ]=i, Rank[ SA[i] ]=i。 后缀i,j的LCP为min{ Height[ Rank[i]+1 \

[总结] 后缀数组学习笔记

人走茶凉 提交于 2020-01-19 02:52:09
$ \(emmm\) 又开了字符串的新坑,下一个阶段大概就是学习后缀家族吧... 没有 紧跟机房里神仙的步伐 先学后缀数组好了 概念 参考博客-> 戳我戳我 求出来SA数组就看了我半天... 放一个板子自己感觉难理解的东西都在注释里了 #include<set> #include<map> #include<cmath> #include<queue> #include<cctype> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using std::min; using std::max; using std::swap; using std::vector; typedef double db; typedef long long ll; #define pb(A) push_back(A) #define pii std::pair<int,int> #define all(A) A.begin(),A.end() #define mp(A,B) std::make_pair(A,B) namespace NewweN{ const int N=1e6+5; int x[N],y[N],c[N]; char s[N];int n,m,num