CH 1402 - 后缀数组 - [字符串hash]
题目链接:传送门
描述
后缀数组 (SA) 是一种重要的数据结构,通常使用倍增或者DC3算法实现,这超出了我们的讨论范围。
在本题中,我们希望使用快排、Hash与二分实现一个简单的 $O(n \log^2 n )$ 的后缀数组求法。
详细地说,给定一个长度为 n 的字符串S(下标 0~n-1),我们可以用整数 k(0≤k<n) 表示字符串S的后缀 S(k~n-1)。
把字符串S的所有后缀按照字典序排列,排名为 i 的后缀记为 SA[i]。额外地,我们考虑排名为 i 的后缀与排名为 i-1 的后缀,把二者的最长公共前缀的长度记为 Height[i]。
我们的任务就是求出SA与Height这两个数组。
输入格式
一个字符串,长度不超过30万。
输出格式
第一行为数组SA,相邻两个整数用1个空格隔开。
第二行为数组Height,相邻两个整数用1个空格隔开,特别地,假设Height[1]=0。
样例输入
ponoiiipoi
样例输出
9 4 5 6 2 8 3 1 7 0
0 1 2 1 0 0 2 1 0 2
样例解释
排名第一(最小)的后缀是9(S[9~9],即字符串 i),第二的是后缀4(S[4~9],即字符串iiipoi),第三的是后缀5(S[5~9],即字符串iipoi)以此类推。Height[2]表示排名第2与第1的后缀的最长公共前缀,长度为1,Height[3]表示排名第3与第2的后缀的最长公共前缀,长度为2,以此类推。
题解:
假设字符串长度为 $N$,那么如果用暴力的方式来比较两个后缀子串的字典序大小(以及求最长公共前缀的长度),显然一次比较是 $O\left( {N} \right)$ 的时间复杂度,
如果用快排对 $N$ 个后缀子串进行排序,那么就要 $O(N^2 \log N)$ 的时间复杂度,
我们尝试考虑优化的地方:比较两个字符串的时间,从 $O(N)$ 降到 $O(\log N)$,
对于两个后缀子串,或者更一般的,对于两个字符串,怎么更快速的比较字典序大小,或者,怎么更快速求的最长公共前缀?
容易想到,可以二分最长公共前缀的长度,用字符串哈希 $O(1)$ 判断是否两个前缀子串是否一样,
然后判断两个字符串中哪个字典序更大就很简单了,去掉最长公共前缀,比较一下剩下的第一个字符即可。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull; const int P=;
const int maxn=+; char s[maxn];
int len;
int sa[maxn],h[maxn]; ull pre[maxn],Ppow[maxn];
void pretreat()
{
pre[]=;
Ppow[]=;
for(int i=;i<=len;i++)
{
pre[i]=pre[i-]*P+(s[i]-'a'+);
Ppow[i]=Ppow[i-]*P;
}
} inline bool isSame(int l1,int r1,int l2,int r2)
{
return pre[r1]-pre[l1-]*Ppow[r1-(l1-)] == pre[r2]-pre[l2-]*Ppow[r2-(l2-)];
}
inline int maxpre(int a,int b)
{
int l=,r=min(len-a+,len-b+),mid;
while(l<r)
{
mid=(l+r)/+;
if(isSame(a,a+mid-,b,b+mid-)) l=mid;
else r=mid-;
}
return l;
}
bool cmp(int a,int b)
{
int mp=maxpre(a,b);
return s[a+mp]<=s[b+mp];
} int main()
{
scanf("%s",s+);
len=strlen(s+);
pretreat();
for(int i=;i<=len;i++) sa[i]=i;
sort(sa+,sa+len+,cmp);
for(int i=;i<=len;i++)
{
if(i==) h[i]=;
else h[i]=maxpre(sa[i-],sa[i]);
printf("%d%c",sa[i]-,i<len?' ':'\n');
}
for(int i=;i<=len;i++) printf("%d%c",h[i],i<len?' ':'\n');
}
1A开心
时间复杂度:
排序 $O(N \log^2 N)$,计算Height数组 $O(N \log N)$,总时间复杂度 $O(N \log^2 N)$。
CH 1402 - 后缀数组 - [字符串hash]的更多相关文章
- 1402 后缀数组 (hash+二分)
描述 后缀数组 (SA) 是一种重要的数据结构,通常使用倍增或者DC3算法实现,这超出了我们的讨论范围.在本题中,我们希望使用快排.Hash与二分实现一个简单的 O(n log^2n ) 的后缀数组 ...
- CH1402 后缀数组【Hash】【字符串】【二分】
1402 后缀数组 0x10「基本数据结构」例题 描述 后缀数组 (SA) 是一种重要的数据结构,通常使用倍增或者DC3算法实现,这超出了我们的讨论范围.在本题中,我们希望使用快排.Hash与二分实现 ...
- [poj 1743] Musical Theme 后缀数组 or hash
Musical Theme 题意 给出n个1-88组成的音符,让找出一个最长的连续子序列,满足以下条件: 长度大于5 不重叠的出现两次(这里的出现可以经过变调,即这个序列的每个数字全都加上一个整数x) ...
- bnuoj 34990(后缀数组 或 hash+二分)
后缀数组倍增算法超时,听说用3DC可以勉强过,不愿写了,直接用hash+二分求出log(n)的时间查询两个字符串之间的任意两个位置的最长前缀. 我自己在想hash的时候一直在考虑hash成数值时MOD ...
- BZOJ 4278: [ONTAK2015]Tasowanie (后缀数组 / 二分+hash)
直接归并,然后如果哪边的后缀字典序比较小就去哪边,然后就可以后缀数组 博客传送门- 但是本蒟蒻不会后缀数组 Upd:Upd:Upd:现在会了233.一道差不多的题:BZOJ 1692: [Usaco2 ...
- BZOJ 1692: [Usaco2007 Dec]队列变换 (后缀数组/二分+Hash)
跟BZOJ 4278: [ONTAK2015]Tasowanie一模一样 SA的做法就是把原串倒过来接在原串后面,O(nlogn)O(nlogn)O(nlogn)做后缀数组,就能O(1)O(1)O(1 ...
- Poj 3294 Life Forms (后缀数组 + 二分 + Hash)
题目链接: Poj 3294 Life Forms 题目描述: 有n个文本串,问在一半以上的文本串出现过的最长连续子串? 解题思路: 可以把文本串用没有出现过的不同字符连起来,然后求新文本串的heig ...
- 140. 后缀数组(hash + 二分 / 后缀数组)
题目链接 : https://www.acwing.com/problem/content/description/142/ Hash + 二分 #include <bits/stdc++.h& ...
- Suffix Array 后缀数组
后缀数组 顾名思义.SuffixArray(下面有时简称SA) 和字符串的后缀有关. 后缀:字符串中某个位置一直到结尾的子串.(SA中讨论包含了原串和空串).所以共同拥有len+1个后缀. 后缀数组: ...
随机推荐
- Chrome禁止http自动转为https
解决方法 在Chrome浏览器地址栏输入chrome://net-internals/#hsts 在Delete domain security policies 中输入要删除自动转换的域名 原因 将 ...
- mysql数据库分区功能及实例详解
分区听起来怎么感觉是硬盘呀,对没错除了硬盘可以分区数据库现在也支持分区了,分区可以解决大数据量的处理问题,下面一起来看一个mysql数据库分区功能及实例详解 一,什么是数据库分区 前段时间写过一篇 ...
- system函数遇到的问题
这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数中调用的命令也都一切正常.就没理这个bug,以 ...
- s:iterator 标签使用错误记录
<s:iterator value="newMarriageMoveList" id='tpNewMarriage' status="number"> ...
- Redis高可用详解:持久化技术及方案选择
文章摘自:https://www.cnblogs.com/kismetv/p/9137897.html 前言 在上一篇文章中,介绍了Redis的内存模型,从这篇文章开始,将依次介绍Redis高可用相关 ...
- 用Python来玩微信跳一跳
微信2017年12月28日发布了新版本,在小程序里面有一个跳一跳小游戏,试着点一点玩了下.第二天刚好在一篇技术公众号中,看到有大神用Python代码计算出按压时间,向手机发送android adb命令 ...
- [Big Data - Codis, Mycat(cobar)] 企业互联网+转型实战:如何进行PB级别数据的架构变迁
随着DT时代的来临,数据对于企业经营决策的价值日益凸显,而企业在进行互联网+转型的过程中,如何让数据架构平滑迁移到大数据平台,对于传统业务的转型升级至关重要.企业IT部门该如何进行PB级别大数据平台的 ...
- 每日英语:Mrs. Obama Takes Stab at Ping-Pong Diplomacy
U.S. first lady Michelle Obama took ping-pong diplomacy to a new level on Friday on her weeklong tou ...
- linux每日命令(14):less命令
less 工具也是对文件或其它输出进行分页显示的工具,应该说是linux正统查看文件内容的工具,功能极其强大.less 的用法比起 more 更加的有弹性.在 more 的时候,我们并没有办法向前面翻 ...
- Android Launcher分析和修改11——自定义分页指示器(paged_view_indicator)
Android4.0的Launcher自带了一个简单的分页指示器,就是Hotseat上面那个线段,这个本质上是一个ImageView利用.9.png图片做,效果实在是不太美观,用测试人员的话,太丑了. ...