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

这个题是bzoj权限题QvQ
于是只好自己和hzwer学长的标称对拍
其实一开始我的思路是差不多的
构造后缀数组,字典序为SA,然后随便枚举一下
只不过我忽略了一个重要的性质
使得我的效率变成了O(n^3)
然而只要用到下面这个性质,效率就只有O(n^2):
因为子串是后缀的前缀,
而SA[i]和SA[i-1]的前height[i]位本质又是相同的,
因重复的子串在SA[i-1]已经往后扫过了
所以串SA[i]只需要判断height[i]+1位~最后一位构成的前缀能往后扩展多少即可。
原因:每个子串只出现过一次,共n^2个子串

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. #define MAXN (3000+10)
  5. using namespace std;
  6. int wa[MAXN],wb[MAXN],wt[MAXN];
  7. char r[MAXN];
  8. int Height[MAXN],SA[MAXN],Rank[MAXN];
  9. int n,m=;
  10.  
  11. bool cmp(int *y,int a,int b,int k)
  12. {
  13. int arank1=y[a];
  14. int brank1=y[b];
  15. int arank2=a+k>=n?-:y[a+k];
  16. int brank2=b+k>=n?-:y[b+k];
  17. return arank1==brank1 && arank2==brank2;
  18. }
  19.  
  20. void Build_SA()
  21. {
  22. int *x=wa,*y=wb;
  23. for (int i=;i<m;++i) wt[i]=;
  24. for (int i=;i<n;++i) wt[x[i]=r[i]]++;
  25. for (int i=;i<m;++i) wt[i]+=wt[i-];
  26. for (int i=n-;i>=;--i) SA[--wt[x[i]]]=i;
  27.  
  28. for (int j=;j<=n;j<<=)
  29. {
  30. int p=;
  31. for (int i=n-j;i<n;++i) y[p++]=i;
  32. for (int i=;i<n;++i) if (SA[i]>=j) y[p++]=SA[i]-j;
  33.  
  34. for (int i=;i<m;++i) wt[i]=;
  35. for (int i=;i<n;++i) wt[x[y[i]]]++;
  36. for (int i=;i<m;++i) wt[i]+=wt[i-];
  37. for (int i=n-;i>=;--i) SA[--wt[x[y[i]]]]=y[i];
  38.  
  39. m=;swap(x,y);
  40. x[SA[]]=;
  41. for (int i=;i<n;++i)
  42. x[SA[i]]=cmp(y,SA[i],SA[i-],j)?m-:m++;
  43. if (m>=n) break;
  44. }
  45. }
  46.  
  47. void Build_Height()
  48. {
  49. for (int i=;i<n;++i) Rank[SA[i]]=i;
  50. Height[]=;
  51. int k=;
  52. for (int i=;i<n;++i)
  53. {
  54. if (!Rank[i]) continue;
  55. if (k) k--;
  56. int j=SA[Rank[i]-];
  57. while (r[i+k]==r[j+k]) ++k;
  58. Height[Rank[i]]=k;
  59. }
  60. }
  61.  
  62. int main()
  63. {
  64. scanf("%d%s",&n,r);
  65. Build_SA();
  66. Build_Height();
  67. for (int i=;i<n-;++i)
  68. {
  69. for (int j=Height[i]+;j<=n-SA[i];++j)//这里非常的妙啊
  70. {
  71. int k=i+;
  72. while (Height[k]>=j) ++k;
  73. if (k-i>) printf("%d\n",k-i);
  74. }
  75. }
  76. }

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

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

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

  2. 【BZOJ2251】[2010Beijing Wc]外星联络 后缀数组

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

  3. BZOJ2251 [2010Beijing Wc]外星联络 后缀数组 + Height数组

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

  4. [bzoj2251][2010Beijing Wc]外星联络——后缀数组+暴力求解

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

  5. 2251: [2010Beijing Wc]外星联络

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

  6. BZOJ 2251: [2010Beijing Wc]外星联络

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

  7. ●BZOJ 2251 [2010Beijing Wc]外星联络

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

  8. bzoj 2251: [2010Beijing Wc]外星联络【SA】

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

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

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

随机推荐

  1. 【redis中键的生存时间(expire) 】

    1.redis中可以使用expire命令设置一个键的生存时间,到时间后redis会自动删除它      expire      设置生存时间(单位/秒)      pexpire    设置生存时间( ...

  2. 第三节:我的第一个Java程序

    一.编写我的第一个Java程序流程: 1.新建一个文本文档:在电脑任意位置“右击”----->选择“新建”----->选择“文本文档”: 2.修改文档名与后缀名:“右击”新建的文本文档-- ...

  3. oracle中scott用户的创建

    原创作品,转载请在文章开头显眼位置注明出处:https://www.cnblogs.com/sunshine5683/p/10046716.html 今天,接着上次的学习进度继续前进,在此过程中,使用 ...

  4. 13、springboot之jpa

    导入包,不多说 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spr ...

  5. Win10+Ubuntu双系统安装

    笔者使用的是华硕FX50J装的双系统,之前使用过Dell的游闸安装过,但是没有碰到那么多问题.所以觉得有必要记录下.安装双系统之前,电脑先安装了win10(win10也崩过几次).下面开始安装双系统步 ...

  6. Code Signal_练习题_Minesweeper

    In the popular Minesweeper game you have a board with some mines and those cells that don't contain ...

  7. csharp:获取 DNS、网关、子网掩码、IP

    /// <summary> /// DNS.网关.子网掩码.IP /// 涂聚文 2015 /// </summary> public class IPAddressStrin ...

  8. LNMP笔记:阿里云32位 CentOS 5.4 配置 LNMP环境

    最近比较郁闷的是 WordPress大学 服务器故障,由于诸多原因没及时处理,导致10多天无法访问.倡萌也是刚接触服务器环境配置,维护的确力不从心,没办法排查出错误根源,所以只好重置系统盘,重新配置L ...

  9. CSS3D动画制作一个3d旋转的筛子

    希望这个demo能让大家理解CSS3的3d空间动画(其实是个假3D) 首先给一个3d的解剖图,x/y/z轴线轴线已经标出 下面附上添加特效的动画旋转 可以根据demo并参考上面解剖图进行理解 < ...

  10. UPDATE语句总结

    一.基本语句 1.SQL UPDATE 语法 UPDATE table_name SET column1 = value1, column2 = value2, ... WHERE condition ...