后缀数组
来源:互联网 发布:软件安装管理器 知乎 编辑:程序博客网 时间:2024/05/21 09:20
后缀数组是处理字符串问题的一个非常常用而实用的工具,
比之后缀树,它的编程难度较低,复杂度较优,可以说几乎能替代后缀树
那他到底是个什么东西呢
其实就是一个字符串的所有后缀按字典序大小排序后的得到的字符串组
这个字符串组最有用的数两个东西:
那么这么构造这两个函数呢?
暴力排序?
显然不行,复杂度太高
我们可以考虑使用倍增思想和基数排序优化
先计算出每个后缀长度为
而后通过基数排序排除每个后缀长度为
(对于左端点为i的后缀,
因为每个后缀长度不同,所以永远不可能相等
所以当当前的前缀组成的字符串组每个字符串均不相同时,即可结束循环
代码如下:
void get_sa(int n,int m){//n代表原字符串长度,m代表当前不重复前缀的个数 memset(cnt,0,sizeof(cnt)); for(int i=1;i<=n;i++)cnt[cmp1[i]=s[i]]++; for(int i=1;i<=m;i++)cnt[i]+=cnt[i-1]; for(int i=n;i>=1;i--)sa[cnt[cmp1[i]]--]=i; for(int d=1;d<=n;d*=2){//用每个后缀长度为d的前缀的大小关系推导长度为2d的大小关系 int tp=0; //按第二关键字排序 for(int i=n-d+1;i<=n;i++)cmp2[++tp]=i;//以这些位置为起点的后缀的当前前缀的第二关键字为空 for(int i=1;i<=n;i++)if(sa[i]>d)cmp2[++tp]=sa[i]-d;//按长度为d的前缀的字典序for,若第一关键字完全则加入 //按第一关键字排序 memset(cnt,0,sizeof(cnt)); for(int i=1;i<=n;i++)cnt[cmp1[cmp2[i]]]++; //cmp2[i]即按第二关键字排序好的前缀所属的后缀编号,cmp1[cmp2[i]]即该前缀第一关键字的字典序大小顺序 for(int i=1;i<=m;i++)cnt[i]+=cnt[i-1]; for(int i=n;i>=1;i--)sa[cnt[cmp1[cmp2[i]]]--]=cmp2[i];//基数排序 for(int i=1;i<=n;i++)cmp2[i]=cmp1[i];//cmp1数组在下述过程中会变化,因此用cmp2数组来替代tmp数组的作用 int pre=0; for(int i=1;i<=n;i++){ if(cmp2[sa[i]]!=cmp2[sa[i-1]]||cmp2[sa[i]+d]!=cmp2[sa[i-1]+d])pre++; //已按字典序排好,若排名为i的字符串与i-1不相等,那么他的字典序排名为i-1的排名加1,否则相等 cmp1[sa[i]]=pre; } if(pre>=n)break;//已经比较出每个后缀的大小关系,再进行倍增没有意义 m=pre; } for(int i=1;i<=n;i++)Rank[sa[i]]=i;}
这样,我们就完成了求取后缀数组的操作
那某,这东东有什么用呢,反正很有用就对了,去多刷点题吧
阅读全文
1 0
- 后缀树/后缀数组
- 后缀树 后缀数组
- 【后缀数组】后缀排序
- 后缀数组
- 后缀数组
- 后缀数组
- 后缀数组
- 后缀数组
- 后缀数组
- 后缀数组
- 后缀数组
- 后缀数组
- 后缀数组
- 后缀数组
- 后缀数组
- 后缀数组
- 后缀数组
- 后缀数组
- plsql连接本地oracle和远程oracle
- 多重背包问题的三种复杂度解法,O(n * w * c)、O(n*w*log c)和O(n * w)。
- C# webBrowser写模拟器时的javascript脚本调用问题
- 欧拉通路
- htmlunit使用代理IP
- 后缀数组
- mybatis框架及原理
- CentOS7 安装 vsftpd 完整版
- (三)简单工厂模式详解
- ARM指令中如何判断一个立即数是有效立即数
- [7.9] 纪中C组
- OpenCV3 Python语言实现 笔记1
- GalaxyOJ-687 (离散化)
- 递推问题之“佐罗”的烦恼