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个后缀. 后缀数组: ...
随机推荐
- Linux ext3/ext4数据恢复
2012年12月9日 测试环境: Ubuntu 12.04 X86 +ext4 恢复文件使用的工具:extundelete(点击下载) 说明:当文件异常消失或者rm误删除后,避免在该分区中继 ...
- KeyTool 和 OpenSSL 相互转换 [转]
REM 生成自签名 CA 证书 REM Win32 OpenSSL REM http://slproweb.com/products/Win32OpenSSL.html REM How to crea ...
- latex学习(四)tlmgr
官网说明文档:https://tug.org/texlive/doc/tlmgr.html,2018版已经被冻结了,所以tlmgr也不会更新了,要等到下一个大的版本才能更新. 1.用tlmgr查看已经 ...
- C# 给枚举类型增加一个备注特性
/// <summary> /// 备注特性 /// </summary> public class RemarkAttribute : Attribute { /// < ...
- Atitit 数据库表文档生成解决方案
Atitit 数据库表文档生成解决方案 1.1. Sql dml文件结构法 最快速1 1.2. Sql法+sp存储过程 (表格式样)1 1.3. Navicate uml法 (uml格式)2 1.4. ...
- Atitit 验证 数字验证 非空验证的最佳算法 h5
Atitit 验证 数字验证 非空验证的最佳算法 h5 <td><select class="searchBox-select" style=" ...
- 每日英语:Doc, Do I Need A Juice Cleanse?
Some drink only vegetable juice. Others soak in Epsom salts. It's all in the pursuit of ridding the ...
- Json Web Token(JWT)
Json web token (JWT),是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(Si ...
- Java如何与Web服务器连接?
在Java编程中,如何与Web服务器连接? 以下示例演示如何使用net.Socket类的sock.getInetAddress()方法与Web服务器连接. package com.yiibai; im ...
- nginx 反向代理 Nginx 502 Bad Gateway
查看错误日志: 摘要: nginx反向代理出现502错误 通过查看日志发现错误信息 2018/01/10 17:58:20 [crit] 8156#0: *1 connect() to 127.0.0 ...