【Luogu5108】仰望半月的夜空(后缀数组)

题面

洛谷

题解

实名举报这题在比赛之前还不是这个样子的,还被我用SAM给水过去了

很明显求出\(SA\)之后就是按照\(SA\)的顺序从前往后考虑每一个长度,这样可以知道串是什么。

不过如果串相同要左端点最靠左,所以二分包含这个串的区间,用\(RMQ\)求出区间最小值即可。

(其实就是拿来复习SA板子的)

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. using namespace std;
  6. #define MAX 400200
  7. inline int read()
  8. {
  9. int x=0;bool t=false;char ch=getchar();
  10. while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
  11. if(ch=='-')t=true,ch=getchar();
  12. while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
  13. return t?-x:x;
  14. }
  15. int n,sig;
  16. char ch[MAX];
  17. int S[MAX],tot,a[MAX],lg[MAX];
  18. int t[MAX],x[MAX],y[MAX],rk[MAX],SA[MAX],hg[20][MAX],mn[20][MAX];
  19. bool cmp(int i,int j,int k){return y[i]==y[j]&&y[i+k]==y[j+k];}
  20. void GetSA()
  21. {
  22. int m=tot;
  23. for(int i=1;i<=n;++i)t[x[i]=a[i]]++;
  24. for(int i=1;i<=m;++i)t[i]+=t[i-1];
  25. for(int i=n;i>=1;--i)SA[t[x[i]]--]=i;
  26. for(int k=1;k<=n;k<<=1)
  27. {
  28. int p=0;
  29. for(int i=n-k+1;i<=n;++i)y[++p]=i;
  30. for(int i=1;i<=n;++i)if(SA[i]>k)y[++p]=SA[i]-k;
  31. for(int i=1;i<=m;++i)t[i]=0;
  32. for(int i=1;i<=n;++i)t[x[y[i]]]++;
  33. for(int i=1;i<=m;++i)t[i]+=t[i-1];
  34. for(int i=n;i>=1;--i)SA[t[x[y[i]]]--]=y[i];
  35. swap(x,y);x[SA[1]]=p=1;
  36. for(int i=2;i<=n;++i)x[SA[i]]=cmp(SA[i],SA[i-1],k)?p:++p;
  37. if(p>=n)break;m=p;
  38. }
  39. for(int i=1;i<=n;++i)rk[SA[i]]=i;
  40. for(int i=2;i<=n;++i)lg[i]=lg[i>>1]+1;
  41. for(int i=1,j=0;i<=n;++i)
  42. {
  43. if(j)--j;
  44. while(a[i+j]==a[SA[rk[i]-1]+j])++j;
  45. hg[0][rk[i]]=j;
  46. }
  47. for(int j=1;j<=lg[n];++j)
  48. for(int i=1;i+(1<<j)-1<=n;++i)
  49. hg[j][i]=min(hg[j-1][i],hg[j-1][i+(1<<(j-1))]);
  50. for(int i=1;i<=n;++i)mn[0][i]=SA[i];
  51. for(int j=1;j<=lg[n];++j)
  52. for(int i=1;i+(1<<j)-1<=n;++i)
  53. mn[j][i]=min(mn[j-1][i],mn[j-1][i+(1<<(j-1))]);
  54. }
  55. int lcp(int i,int j)
  56. {
  57. if(i==j)return 1e9;i=rk[i];j=rk[j];
  58. if(i>j)swap(i,j);i+=1;int k=lg[j-i+1];
  59. return min(hg[k][i],hg[k][j-(1<<k)+1]);
  60. }
  61. int RMQ(int i,int j)
  62. {
  63. if(i>j)swap(i,j);int k=lg[j-i+1];
  64. return min(mn[k][i],mn[k][j-(1<<k)+1]);
  65. }
  66. int main()
  67. {
  68. sig=read();n=read();
  69. if(sig==26)
  70. {
  71. scanf("%s",ch+1);n=strlen(ch+1);
  72. for(int i=1;i<=n;++i)a[i]=ch[i]-96;
  73. }
  74. else for(int i=1;i<=n;++i)a[i]=read();
  75. for(int i=1;i<=n;++i)S[++tot]=a[i];
  76. sort(&S[1],&S[n+1]);tot=unique(&S[1],&S[n+1])-S-1;
  77. for(int i=1;i<=n;++i)a[i]=lower_bound(&S[1],&S[tot+1],a[i])-S;
  78. GetSA();
  79. for(int i=1,p=1;i<=n;++i)
  80. {
  81. while(n-SA[p]+1<i)++p;
  82. int l=p+1,r=n,ret=p;
  83. while(l<=r)
  84. {
  85. int mid=(l+r)>>1;
  86. if(lcp(SA[p],SA[mid])>=i)l=mid+1,ret=mid;
  87. else r=mid-1;
  88. }
  89. printf("%d ",RMQ(p,ret));
  90. }
  91. puts("");return 0;
  92. }

【Luogu5108】仰望半月的夜空(后缀数组)的更多相关文章

  1. 洛谷P5108 仰望半月的夜空(后缀数组)

    题意 题目链接 Sol warning:下面这个做法只有95分,本地拍了1w+组都没找到错误我表示十分无能为力 我们考虑每个串的排名去更新答案,显然排名为\(1\)的后缀的前缀一定是当前长度的字典序最 ...

  2. luoguP5108 仰望半月的夜空 [官方?]题解 后缀数组 / 后缀树 / 后缀自动机 + 线段树 / st表 + 二分

    仰望半月的夜空 题解 可以的话,支持一下原作吧... 这道题数据很弱..... 因此各种乱搞估计都是能过的.... 算法一 暴力长度然后判断判断,复杂度\(O(n^3)\) 期望得分15分 算法二 通 ...

  3. 洛谷 P5108 仰望半月的夜空 解题报告

    P5108 仰望半月的夜空 题目描述 半月的夜空中,寄托了多少人与人之间的思念啊 曦月知道,这些思念会汇集成一个字符串\(S(n = |S|)\) 由于思念汇集的过于复杂,因此曦月希望提炼出所有的思念 ...

  4. 后缀数组的倍增算法(Prefix Doubling)

    后缀数组的倍增算法(Prefix Doubling) 文本内容除特殊注明外,均在知识共享署名-非商业性使用-相同方式共享 3.0协议下提供,附加条款亦可能应用. 最近在自学习BWT算法(Burrows ...

  5. BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]

    4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...

  6. BZOJ 1692: [Usaco2007 Dec]队列变换 [后缀数组 贪心]

    1692: [Usaco2007 Dec]队列变换 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1383  Solved: 582[Submit][St ...

  7. POJ3693 Maximum repetition substring [后缀数组 ST表]

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9458   Acc ...

  8. POJ1743 Musical Theme [后缀数组]

    Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 27539   Accepted: 9290 De ...

  9. 后缀数组(suffix array)详解

    写在前面 在字符串处理当中,后缀树和后缀数组都是非常有力的工具. 其中后缀树大家了解得比较多,关于后缀数组则很少见于国内的资料. 其实后缀数组是后缀树的一个非常精巧的替代品,它比后缀树容易编程实现, ...

随机推荐

  1. C# 获取文件MD5值的方法

    可用于对比文件是否相同 /// <summary> /// 获取文件MD5值 /// </summary> /// <param name="fileName& ...

  2. Ionic 入门与实战之第二章第一节:Ionic 环境搭建之开发环境配置

    原文发表于我的技术博客 本文是「Ionic 入门与实战」系列连载的第二章第一节,主要对 Ionic 的开发环境配置做了简要的介绍,本文介绍的开发环境为 Mac 系统,Windows 系统基本类似,少许 ...

  3. squid代理http和https方式上网的操作记录

    需求说明:公司IDC机房有一台服务器A,只有内网环境:192.168.1.150现在需要让这台服务器能对外访问,能正常访问http和https请求(即80端口和443端口)操作思路:在IDC机房里另找 ...

  4. SQL多表查询总结

    前言 连接查询包括合并.内连接.外连接和交叉连接,如果涉及多表查询,了解这些连接的特点很重要.只有真正了解它们之间的区别,才能正确使用. 一.Union UNION 操作符用于合并两个或多个 SELE ...

  5. ResultSet集合查询字段名称(转载)

    转自:https://blog.csdn.net/song_litao/article/details/84751351 public List<String> getColumnName ...

  6. C++编写四则运算生成程序

    1.计划方案 按照预定计划,在时限为一周时,完成该程序所需时间大致如下表: PSP2.1 Personal Software Process Stages Time Planning 计划 · Est ...

  7. 我的github地址

    链接:https://github.com/long0123/test.git   推送项目的github的大致步骤如下: 1.在本地创建一个项目仓库,可以放些基本的项目文件 2.cd至该目录下 3. ...

  8. Sprint会议计划

    经过饭后的宿舍激烈会议之后...... 1.我们的MASTER是组员董大为 2.这次sprint的目标是四则运算系统 3.每天例会时间地点:每天晚饭后在宿舍 4.实现四则运算的基本功能前期已经完成得差 ...

  9. SpringMVC运行流称总结(DispatcherServlet-doDispatch)

    1.运行流程 1).所有请求都是由前端控制器处理: 2).请求路径和RequestMapping进行对比, 3).找到就直接利用反射调用方法 4).把方法返回值作为页面地址,直接转发到这个页面: 四步 ...

  10. Chrome查看HTTP

    查找cookie 补充: 接口调试使用postman挺不错的.以前每次都自己写一个ajax来进行接收调试. 如:用post发送json数据给接口,得到json数据. 工具有时候能让效率大大提升,要学会 ...