描述

后缀数组 (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这两个数组。<n) i="" i-1="" p="">

输入格式

一个字符串,长度不超过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,以此类推。

思路:因为要按照字典序排序,既然排序,那么就想到了快排sort。

那就要自定义比较函数,如果对于两个字符串O(n)扫描比较,那么总体复杂度O(n2logn)

我们可以二分比较的长度,对于同样长的字符串通过对字符串hash得到的hash值比较其是否相同,O(logn)找出其不同位置,然后比较该位置大小,这样复杂度O(nlog2n)

#include<bits/stdc++.h>
using namespace std; const int maxn = ;
unsigned long long f[maxn],p[maxn];
char word[maxn];
int n;
struct Node
{
int pos;
int hei;
Node(int x = ,int h=):pos(x),hei(h) {}
} node[maxn]; unsigned long long getf(int l,int r)
{
return f[r] - f[l-]*p[r-l+];
} int cal(Node a,Node b)
{
int lena = n - a.pos + ;
int lenb = n - b.pos + ;
int l = ,r = min(lena,lenb);
while(l <= r)
{
int mid = (l+r)>>;
if(getf(a.pos,a.pos+mid-) == getf(b.pos,b.pos+mid-))
{
l = mid + ;
}
else
{
r = mid - ;
}
}
return l-;
}
bool cmp(Node a,Node b)
{
int t = cal(a,b);
return word[a.pos+t] < word[b.pos+t];
}
int main()
{
scanf("%s",word+);
n = strlen(word+);
p[] = ;
f[] = ;
for(int i=; i<=n; i++)
{
node[i].pos = i;
f[i] = f[i-] * + word[i] - 'a' + ;
p[i] = p[i-]*;
}
sort(node+,node++n,cmp);
for(int i=; i<=n; i++)
{
node[i].hei = cal(node[i-],node[i]);
}
for(int i=; i<=n; i++)
{
printf("%d",node[i].pos-);
if(i != n)
printf(" ");
else
printf("\n");
}
for(int i=; i<=n; i++)
{
printf("%d",node[i].hei);
if(i != n)
printf(" ");
else
printf("\n");
}
}

1402 后缀数组 (hash+二分)的更多相关文章

  1. cogs2223. [SDOI2016 Round1] 生成魔咒(后缀数组 hash 二分 set

    题意:对一个空串每次在后面加一个字符,问每加完一次得到的字符串有几个不同的子串. 思路:每个子串都是某个后缀的前缀,对于每个后缀求出他能贡献出之前没有出现过的前缀的个数,答案累加就行. 要求每个后缀的 ...

  2. FJUT3703 这还是一道数论题(二分 + hash + manacher 或者 STL + hash 或者 后缀数组 + hash)题解

    Problem Description 最后来个字符串签个到吧,这题其实并不难,所需的算法比较基础,甚至你们最近还上过课. 为了降低难度,免得所有人爆零.这里给几个提示的关键字 :字符串,回文,二分, ...

  3. CH 1402 - 后缀数组 - [字符串hash]

    题目链接:传送门 描述 后缀数组 (SA) 是一种重要的数据结构,通常使用倍增或者DC3算法实现,这超出了我们的讨论范围. 在本题中,我们希望使用快排.Hash与二分实现一个简单的 $O(n \log ...

  4. UVALive - 4513 Stammering Aliens ——(hash+二分 || 后缀数组加二分)

    题意:找一个出现了m次的最长子串,以及这时的最右的位置. hash的话代码还是比较好写的,,但是时间比SA多很多.. #include <stdio.h> #include <alg ...

  5. [bzoj1717][Usaco2006 Dec]Milk Patterns 产奶的模式 (hash构造后缀数组,二分答案)

    以后似乎终于不用去学后缀数组的倍增搞法||DC3等blablaSXBK的方法了= = 定义(来自关于后缀数组的那篇国家集训队论文..) 后缀数组:后缀数组SA是一个一维数组,它保存1..n的某个排列S ...

  6. Uva12206 Stammering Aliens 后缀数组&&Hash

    Dr. Ellie Arroway has established contact with an extraterrestrial civilization. However, all effort ...

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

    Life Forms Problem's Link Mean: 给你n个串,让你找出出现次数大于n/2的最长公共子串.如果有多个,按字典序排列输出. analyse: 经典题. 直接二分判断答案. 判 ...

  8. 后缀数组 hash求LCP BZOJ 4310: 跳蚤

    后缀数组的题博客里没放进去过..所以挖了一题写写 充实下博客 顺便留作板子.. 一个字符串S中 内容不同的子串 有 sigma{n-sa[i]+1-h[i]}   (噢 这里的h[]就是大家熟知的he ...

  9. HDU-4622 Reincarnation 后缀数组 | Hash,维护和,扫描

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4622 题意:给一个字符串,询问某字串的不同字串的个数. 可以用后缀数组来解决,复杂度O(n).先求出倍 ...

随机推荐

  1. yum安装软件内容

    linux  yum源改为阿里yum源 1.备份 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.back ...

  2. 【ftp】主动模式和被动模式

    来自:http://blog.csdn.net/liuhelong12/article/details/50218311 原博主不让转载全文,不过下面这部分是原博主转载别人的,所以我拿过来应该没问题吧 ...

  3. kali linux 更新问题

    1.使用一次更新和升级软件替换 apt-get install && apt -y full -upgrade 之后使用 reboot重启    系统,重启之后 再次使用命令   ap ...

  4. java----AOP框架理解

    面向切面编程: 通过动态代理+加配置文件 目的解耦 给主逻辑添加一些修饰功能,但是不在主逻辑代码中进行修改,有点类似python中的装饰器,调用方法还是是通过接口的那个类来调用: import jav ...

  5. poj3662 二分+最短路

    /* 给定一张无向图,要求找到1-n的路径,该路径上第k+1大的边是所有路径上最小的 如果没有1-n的路,那么输出-1 二分答案mid,遍历一次所有边,如果边权小于mid,则设为0,大于mid,则设为 ...

  6. hdu4738 求割边

    细节题:1.如果图不连通,则输出0 2.如果图没有桥,本身是双联通图,则输出-1 3.如果最小的桥权值为0,任然要输出1 #include<bits/stdc++.h> using nam ...

  7. CF979E

    非常好的dp,非常考dp的能力 很显然是个计数问题,那么很显然要么是排列组合,要么是递推,这道题很显然递推的面更大一些. 那么我们来设计一下状态: 设状态f[i][j][k][p]表示目前到了第i个点 ...

  8. Java SimpleDateFormat 中英文时间格式化转换

    2015年08月29日 17:37:43 阅读数:32459 SimpleDateFormat是一个以与语言环境有关的方式来格式化和解析日期的具体类.它允许进行格式化(日期 -> 文本).解析( ...

  9. MySQL修改数据表存储引擎的3种方法介绍

    这篇文章主要介绍了MySQL修改数据表存储引擎的3种方法介绍,分别是直接修改.导出导入.创建插入3种方法, 可以参考下   MySQL作为最常用的数据库,经常遇到各种各样的问题.今天要说的就是表存储引 ...

  10. 重建控制文件报错 ORA-01503 ORA-01192

    1. 错误信息 ORA-: CREATE CONTROLFILE failed ORA-: must have at least one enabled thread 2. 重建脚本 CREATE C ...