bzoj 2251: [2010Beijing Wc]外星联络 后缀数组

时间:2021-10-23 09:52:46

2251: [2010Beijing Wc]外星联络

Time Limit: 30 Sec  Memory Limit: 256 MB
Submit: 424  Solved: 232
[Submit][Status][Discuss]

Description

小 P 在看过电影《超时空接触》(Contact)之后被深深的打动,决心致力于寻
找外星人的事业。于是,他每天晚上都爬在屋顶上试图用自己的收音机收听外星
人发来的信息。虽然他收听到的仅仅是一些噪声,但是他还是按照这些噪声的高
低电平将接收到的信号改写为由 0 和 1 构成的串, 并坚信外星人的信息就隐藏在
其中。他认为,外星人发来的信息一定会在他接受到的 01 串中重复出现,所以
他希望找到他接受到的 01 串中所有重复出现次数大于 1 的子串。但是他收到的
信号串实在是太长了,于是,他希望你能编一个程序来帮助他。

Input

输入文件的第一行是一个整数N ,代表小 P 接收到的信号串的长度。
输入文件第二行包含一个长度为N 的 01 串,代表小 P 接收到的信号串。

Output

输出文件的每一行包含一个出现次数大于1 的子串所出现的次数。输出的顺
序按对应的子串的字典序排列。

Sample Input

7
1010101

Sample Output

3
3
2
2
4
3
3
2
2

HINT

对于 100%的数据,满足 0 <=  N     <=3000

  按理说以前写过的算法模板题就不该再写了,但是我后缀数组掌握的确实跟xiang一样,还是再写一遍。

  后缀数组需要将内存开大两倍,这个问题我就不赘述了。主要问题是求height数组,以前总觉得顺序问题很烦,其实也不难,只要搞清楚求height的转移顺序就行,一个位置的height求取就需要它在“字符串位置”中前一个位置的height值就行了,所以for语句应该一次枚举原数组的位置。

  剩下就比较简单了,我用O(n^2)的时间复杂度处理答案,不知道有没有更快的,一点小的注意事项,字典序排序注意起始位置相同的子串的顺序,其顺序与枚举顺序相反。也就是说我们在绕过一个坑的情况下防止跌进另一个坑中。

  最后hbw提到一个将随机字符串后缀数组优化到O(n)的方法,当rank数组最大值为n时直接break掉,貌似这是个简单有用的优化

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define MAXN 3010*2
char str[MAXN];
int sa[MAXN],tsa[MAXN];
int rank[MAXN],trank[MAXN];
int buc[MAXN];
int height[MAXN];
int theight[MAXN];
void IndexSort(int jp,int n)
{
memset(buc,,sizeof(buc));
for (int i=;i<n;i++)buc[rank[i+jp]]++;
for (int i=;i<=n;i++)buc[i]+=buc[i-];
for (int i=n-;i>=;i--)tsa[--buc[rank[i+jp]]]=i;
memset(buc,,sizeof(buc));
for (int i=;i<n;i++)buc[rank[tsa[i]]]++;
for (int i=;i<=n;i++)buc[i]+=buc[i-];
for (int i=n-;i>=;i--)sa[--buc[rank[tsa[i]]]]=tsa[i];
}
void SuffixArray(char* str,int n)
{
for (int i=;i<n;i++)trank[i]=str[i]-''+;
for (int i=;i<n;i++)buc[trank[i]]++;
for (int i=;i<=n;i++)buc[i]+=buc[i-];
for (int i=n-;i>=;i--)sa[--buc[trank[i]]]=i;
for (int i=,x=;i<n;i++)
{
if (!i || trank[sa[i]]!=trank[sa[i-]])x++;
rank[sa[i]]=x;
}
for (int j=;j<n;j=j<<)
{
IndexSort(j,n);
int x=;
for (int i=;i<n;i++)
{
if (!i || rank[sa[i]]!=rank[sa[i-]] || rank[sa[i]+j]!=rank[sa[i-]+j])x++;
trank[sa[i]]=x;
}
for (int i=;i<n;i++)rank[i]=trank[i];
if (x==n)break;
}
}
void InitHeight(int n)
{
for (int i=;i<n;i++)
{
if (rank[i]==)continue;
height[i]=max(height[i-]-,);
while (i+height[i]<n && sa[rank[i]-]+height[i]<n
&& str[i+height[i]]==str[sa[rank[i]-]+height[i]])
height[i]++;
}
for (int i=;i<n;i++)
theight[i]=height[sa[i]];
}
vector<int> vec;
int stack[MAXN],tops=-;
int main()
{
freopen("input.txt","r",stdin);
int n;
int x;
scanf("%d\n",&n);
scanf("%s\n",str);
SuffixArray(str,n);
InitHeight(n);
// for (int i=0;i<n;i++)printf("%d ",sa[i]);printf("\n");
// for (int i=0;i<n;i++)printf("%s\n",str+sa[i]);printf("\n");
// for (int i=0;i<n;i++)printf("%d ",height[i]);printf("\n");
for (int i=;i<n;i++)
{
if (theight[i]<=theight[i-])continue;
x=i;
for (int k=theight[i];k>theight[i-];k--)
{
while (x+<n && theight[x+]>=k)x++;
stack[++tops]=x-i+;
}
while (~tops)
printf("%d\n",stack[tops--]);
}
}

bzoj 2251: [2010Beijing Wc]外星联络 后缀数组的更多相关文章

  1. BZOJ 2251&colon; &lbrack;2010Beijing Wc&rsqb;外星联络

    2251: [2010Beijing Wc]外星联络 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 795  Solved: 477[Submit][ ...

  2. 【BZOJ2251】&lbrack;2010Beijing Wc&rsqb;外星联络 后缀数组

    [BZOJ2251][2010Beijing Wc]外星联络 Description 小 P 在看过电影<超时空接触>(Contact)之后被深深的打动,决心致力于寻找外星人的事业.于是, ...

  3. ●BZOJ 2251 &lbrack;2010Beijing Wc&rsqb;外星联络

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2251 题解: 后缀数组,倍增,RMQ 题意:把重复次数超过 1次的子串按字典序输出它们重复的 ...

  4. BZOJ2251 &lbrack;2010Beijing Wc&rsqb;外星联络 后缀数组 &plus; Height数组

    Code: #include <bits/stdc++.h> #define setIO(s) freopen(s".in", "r", stdin ...

  5. &lbrack;bzoj2251&rsqb;&lbrack;2010Beijing Wc&rsqb;外星联络——后缀数组&plus;暴力求解

    Brief Description 找到 01 串中所有重复出现次数大于 1 的子串.并按字典序输出他们的出现次数. Algorithm Design 求出后缀数组之后,枚举每一个后缀,对于每个后缀从 ...

  6. bzoj 2251&colon; &lbrack;2010Beijing Wc&rsqb;外星联络【SA】

    先求SA,然后按字典序从小到大枚举子串,每到一个后缀从长到短枚举子串(跳过长为he[i]的和前一段重复的子串),然后维护一个点p,保证i~p之间最小的he>=当前枚举长度,p是单调向右移的 然后 ...

  7. 2251&colon; &lbrack;2010Beijing Wc&rsqb;外星联络

    2251: [2010Beijing Wc]外星联络 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 801  Solved: 481[Submit][ ...

  8. 2251&period; &lbrack;2010Beijing Wc&rsqb;外星联络【后缀数组】

    Description 小 P 在看过电影<超时空接触>(Contact)之后被深深的打动,决心致力于寻 找外星人的事业.于是,他每天晚上都爬在屋顶上试图用自己的收音机收听外星 人发来的信 ...

  9. 【BZOJ-2251】外星联络 后缀数组 &plus; 暴力

    2251: [2010Beijing Wc]外星联络 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 670  Solved: 392[Submit][ ...

随机推荐

  1. Git使用实例分析

    记录下James工作中遇到的问题: 1. 在app目录下提交.cfg特制化文件,此时Git和Gerrit结合使用: 2. 对修改文件追加提交: 3. 查看当前目录的所有分支,包括:本地分支和远程分支: ...

  2. 【网络收集】如何修改vs tfs的登录名和密码 &period;

    连接TFS时,如果本机保存了用户的网络密码,不会出现用户名和密码的输入框,若要更换TFS的用户名和密码,需按以下步骤操作:控制面板--->用户账号--->管理网络密码,此时会列出所有保存了 ...

  3. VPN client on linux debian

    Install the pptp-linux and pptp-linux-client: sudo apt-get install pptp-linux pptp-linux-client Crea ...

  4. VPS安装中文语言

    在CentOS VPS下修改语言编码: localedef -c -f UTF-8 -i zh_CN zh_CN.utf8 export LC_ALL=zh_CN.utf8 上面第一步是用来产生编码文 ...

  5. &num;define和typedef在windows上的应用

    typedef的应用 typedef是在计算机编程语言中用来为复杂的声明定义简单的别名. 下面的代码定义了一些常见类型的别名 typedef int INT; typedef unsigned int ...

  6. Tomcat下载,新建自己的项目,模拟server

    一.tomcat下载 下载地址http://tomcat.apache.org/ 打开网页能够看到例如以下内容 在网页左边有Download以下就是能够下载的版本号.如6.0,7.0,8.0: 选择一 ...

  7. 《JavaScript Dom 编程艺术》读书笔记-第5章

    上一篇随笔中记录了用JavaScript建一个基础图片库,但实际上还有很多地方可以改进.第五章将逐步进行改进,这一章里需要明白的道理是达到目标的过程和达到目标同样重要~ 第五章:最佳实践 5.1 过去 ...

  8. 2018春招-今日头条笔试题-第四题(python)

    题目描述:2018春招-今日头条笔试题5题(后附大佬答案-c++版) #-*- coding:utf-8 -*- class Magic: ''' a:用于存储数组a b:用于存储数组b num:用于 ...

  9. &lbrack;6&rsqb; 胶囊体&lpar;Capsule&rpar;图形的生成算法

    顶点数据的生成 bool YfBuildCapsuleVertices ( Yreal radius, Yreal height, Yuint slices, Yuint stacks, YeOrig ...

  10. (CF&num;257&rpar;B&period; Jzzhu and Sequences

    Jzzhu has invented a kind of sequences, they meet the following property: You are given x and y, ple ...