c++ 字符串数组长度排序_数组 | 后缀数组的求法及应用
作者:Andy__lee
链接:https://blog.nowcoder.net/n/6b4a93e186ed4a358321de6a7c3b4f19
来源:牛客网
定义
维基百科 - 后缀数组
让我们来看一下 wiki 上的定义:
在计算机科学里, 后缀数组(英语:suffix array)是一个通过对字符串的所有后缀经过排序后得到的数组。此数据结构被运用于全文索引、数据压缩算法、以及生物信息学。
令字符串
满足
求法
大体思想
这玩意可以使用倍增来求,当然也有常数比较大的
中心思想就是假设我们求出了考虑每个后缀前
目前考虑的长度下,
相信大家看完后肯定是一脸 mb,接下来我来详细的说一下算法过程。
算法过程
首先我们来定义一些变量:
首先按照定义,显然有
也就是说明了这两个数组可以互相
开始时
现在我们考虑如何求出
p = 0;
FOR(i,1,w) tp[++p] = N-w+i;
FOR(i,1,N) if(sa[i] > w) tp[++p] = sa[i]-w;
首先对于长度
然后对于长度
所以代码就是按照上一轮的顺序从小到大枚举了每个长度
之后我们搞个比较高效的排序(基数排序)排一下。
然后因为在这个倍增过程中可能有的后缀的
std::swap(tp,rk); // rk 没用了,当然这里最好写指针交换
rk[sa[1]] = p = 1;
FOR(i,2,N) rk[sa[i]] = (tp[sa[i-1]] == tp[sa[i]] && tp[sa[i-1]+w] == tp[sa[i]+w]) ? p : ++p;
去重的原理和上面的类似:如果前半段和后半段在上一轮的rkrk相同的话那它们当前就是相同的。
然后就做完了。。。。
现在我们要解决的是找到一种高效的排序方法,首先显然你不能用
所以我们考虑
先放一下代码:
inline void sort(){FOR(i,0,M) tax[i] = 0;FOR(i,1,N) tax[rk[i]]++;FOR(i,1,M) tax[i] += tax[i-1];ROF(i,N,1) sa[tax[rk[tp[i]]]--] = tp[i];
}
首先我们把桶清空,然后统计每种
然后我们重点关注最后一句是在干什么。首先我们按第二关键字从大到小枚举(
是不是很好理解?这样后缀数组就写完了。
附上Luogu - 后缀排序的代码:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <climits>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>#define Re register
#define LL long long
#define U unsigned
#define FOR(i,a,b) for(Re int i = a;i <= b;++i)
#define ROF(i,a,b) for(Re int i = a;i >= b;--i)
#define SFOR(i,a,b,c) for(Re int i = a;i <= b;i+=c)
#define SROF(i,a,b,c) for(Re int i = a;i >= b;i-=c)
#define CLR(i,a) memset(i,a,sizeof(i))
#define BR printf("--------------------n")
#define DEBUG(x) std::cerr << #x << '=' << x << std::endlconst int MAXN = 1000000+5;char str[MAXN];
int N,sa[MAXN],tax[MAXN],M;
int pool1[MAXN],*rk = pool1,pool2[MAXN],*tp = pool2;inline void sort(){FOR(i,0,M) tax[i] = 0;FOR(i,1,N) tax[rk[i]]++;FOR(i,1,M) tax[i] += tax[i-1];ROF(i,N,1) sa[tax[rk[tp[i]]]--] = tp[i];
}inline void SuffixSort(){M = 75;FOR(i,1,N) rk[i] = str[i]-'0'+1,tp[i] = i;sort();for(int w = 1,p = 0;p < N;w <<= 1,M = p){p = 0;FOR(i,1,w) tp[++p] = N-w+i;FOR(i,1,N) if(sa[i] > w) tp[++p] = sa[i]-w;sort();std::swap(tp,rk);rk[sa[1]] = p = 1;FOR(i,2,N) rk[sa[i]] = (tp[sa[i-1]] == tp[sa[i]] && tp[sa[i-1]+w] == tp[sa[i]+w]) ? p : ++p;}FOR(i,1,N) printf("%d ",sa[i]);
}int main(){scanf("%s",str+1);N = strlen(str+1);SuffixSort();return 0;
}
Height 数组
后缀数组如果只能排序的话那貌似没什么用,大多数后缀数组题目主要还是考察 Height 数组的性质。
首先扔一些定义。。。
定义
如果直接枚举后缀那还求后缀数组干嘛,所以说我们要考虑能否通过后缀数组求出的信息来线性推出
对于
代码:
inline void get(){int j,k = 0;FOR(i,1,N){if(k) --k;int j = sa[rk[i]-1];while(str[i+k] == str[j+k]) ++k;height[rk[i]] = k;}
}
经典应用
求任意后缀的最大 lcp
这东西随便维护一个区间极值就可以了,
可重叠最长重复子串
意思是求最长的子串使得在字符串中重复出现过。
根据定义就是 height 数组中的最大值
不可重叠最长重复子串
POJ - 1743
我们来考虑二分答案。假设现在我们二分的答案是
然后考虑在一些地方将 height 分开,保证每一段最小
本质不同的子串数量
注意到子串 = 后缀的前缀。
对于排名为
所以答案就是
查看作者更多博客:https://blog.nowcoder.net/rainair
c++ 字符串数组长度排序_数组 | 后缀数组的求法及应用相关推荐
- php读取数组长度,PHP count():获取数组长度
PHP count() 函数用来获取数组长度,也即计算数组元素的个数.另外,count() 函数还可以统计对象中的属性个数. count() 语法如下: int count ( mixed $arr ...
- java 数组对象长度_Java中的数组长度:关于Java中数组长度的所有信息
Java中的数组可以包含多个元素,这取决于对象是如何创建的.为了让用户执行不同的操作,必须知道数组的长度.这篇关于"Java中的数组长度"的文章旨在让我们熟悉用于获取数组长度的操 ...
- 数组-接口2-参数为一个整型数组和数组长度的整数(该数组输入和运算结果),再加一个整数;预期结果是一个整型数组
测试接口的代码说明 适用接口:参数为一个整型数组和数组长度的整数(该数组输入和运算结果),再加一个整数:预期结果是一个整型数组 测试接口的具体代码如下: 注意红色字体,用后续小节中的接口进行替换,进行 ...
- 二维字符数组按长度排序_字符串长度 字符数组长度
1.不带转义字符的字符 如:"abc!x=/",其长度为 7 2.带转义字符的字符串 (1) 字符串"abcn":其中的'n'为转义字符(换行符),计算字符串长 ...
- 字符串系列(二)——“万金油”后缀数组
学习后缀数组有感 (原创,转载请注明出处) 在做一些串的问题时,因为其本身处理比较麻烦,光是比较就要耗费O(n²)的复杂度.因此我们使用后缀数组来进行复杂度的简化. 首先要明确,后缀数组是一种工具,可 ...
- cf244D. Match amp; Catch 字符串hash (模板)或 后缀数组。。。
D. Match & Catch 能够用各种方法做.字符串hash.后缀数组,dp.拓展kmp,字典树.. . 字符串hash(模板) http://blog.csdn.net/gdujian ...
- java对数组进行排序_用Java对数组进行排序所需的最少交换
java对数组进行排序 Problem: 问题: In this problem, we would have an unordered array with consecutive distinct ...
- [转载] java中对数组进行排序_如何在Java中对数组排序
参考链接: Java中main()的有效变体 java中对数组进行排序 Java Array is like a container that can hold a fixed number of t ...
- java中对数组进行排序_如何在Java中对数组排序
java中对数组进行排序 Java Array is like a container that can hold a fixed number of the same type of items, ...
最新文章
- 第十八章 33用重载输出运算符函数实现字符串的输出
- 使用Skywalking实现全链路监
- oracle dbms overflow,Oracle DBA课程系列笔记(12_1)
- ECMALL数据库关系模型的实现
- yolo算法_吴恩达深度学习笔记(100)-目标检测之YOLO 算法讲解
- E	速度即转发(牛客挑战赛48)(树套树)
- 架构设计 | 分布式体系下,服务分层监控策略
- Kaldi 语音识别基础教程
- 专利基本知识及撰写要求
- 万网域名证书如何查询下载_备案域名证书获取
- 自己的作品界面---类似360杀毒软件的界面
- 【动态规划的方法论】
- Python之pip:pip包管理工具的简介、安装、使用方法之详细攻略
- Mysql Where条件执行顺序是从左到右
- linux终端实现骇客帝国的字符雨动画
- luogu P1600 天天爱跑步
- C语言编程规范学习笔记和总结(附华为编程规范机试参考试题)
- Java代码一键生成神器,支持Jpa/Mybatis/plus多种ORM框架,亲测好用
- abaqus算界面脱粘_Abaqus 粘聚力模型(Cohesive Model)
- pcl::lineToLineSegment() 计算空间直线的交点和最小公垂线