给n个字符串,求最长的多于n/2个字符串的公共子串。

依然是二分判定+height分组。

  • 把这n个字符串连接,中间用不同字符隔开,跑后缀数组计算出height;
  • 二分要求的子串长度,判断是否满足:height分组,统计一个组不同的字符串个数是否大于n/2;
  • 最后输出方案,根据二分得出的子串长度的结果,直接再遍历一遍height,因为这儿是有序的后缀所以找到一个就直接输出。
  1. #include<cstdio>
  2. #include<cstring>
  3. #include<cmath>
  4. #include<algorithm>
  5. using namespace std;
  6. #define MAXN 111000
  7.  
  8. int wa[MAXN],wb[MAXN],wv[MAXN],ws[MAXN];
  9. int cmp(int *r,int a,int b,int l){
  10. return r[a]==r[b] && r[a+l]==r[b+l];
  11. }
  12. int sa[MAXN],rank[MAXN],height[MAXN];
  13. void SA(int *r,int n,int m){
  14. int *x=wa,*y=wb;
  15.  
  16. for(int i=; i<m; ++i) ws[i]=;
  17. for(int i=; i<n; ++i) ++ws[x[i]=r[i]];
  18. for(int i=; i<m; ++i) ws[i]+=ws[i-];
  19. for(int i=n-; i>=; --i) sa[--ws[x[i]]]=i;
  20.  
  21. int p=;
  22. for(int j=; p<n; j<<=,m=p){
  23. p=;
  24. for(int i=n-j; i<n; ++i) y[p++]=i;
  25. for(int i=; i<n; ++i) if(sa[i]>=j) y[p++]=sa[i]-j;
  26. for(int i=; i<n; ++i) wv[i]=x[y[i]];
  27. for(int i=; i<m; ++i) ws[i]=;
  28. for(int i=; i<n; ++i) ++ws[wv[i]];
  29. for(int i=; i<m; ++i) ws[i]+=ws[i-];
  30. for(int i=n-; i>=; --i) sa[--ws[wv[i]]]=y[i];
  31. swap(x,y); x[sa[]]=; p=;
  32. for(int i=; i<n; ++i) x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p-:p++;
  33. }
  34.  
  35. for(int i=; i<n; ++i) rank[sa[i]]=i;
  36. int k=;
  37. for(int i=; i<n-; height[rank[i++]]=k){
  38. if(k) --k;
  39. for(int j=sa[rank[i]-]; r[i+k]==r[j+k]; ++k);
  40. }
  41. }
  42.  
  43. int n,m,r[MAXN],belong[MAXN];
  44. bool isok(int len){
  45. int cnt=;
  46. bool vis[]={};
  47. for(int i=; i<=n; ++i){
  48. if(height[i]>=len){
  49. if(!vis[belong[sa[i]]]){
  50. vis[belong[sa[i]]]=;
  51. ++cnt;
  52. }
  53. if(!vis[belong[sa[i-]]]){
  54. vis[belong[sa[i-]]]=;
  55. ++cnt;
  56. }
  57. }else{
  58. if(cnt>(m>>)) return ;
  59. memset(vis,,sizeof(vis));
  60. cnt=;
  61. }
  62. }
  63. return ;
  64. }
  65. void pnt(int len){
  66. int cnt=,idx;
  67. bool vis[]={};
  68. for(int i=; i<=n; ++i){
  69. if(height[i]>=len){
  70. idx=sa[i];
  71. if(!vis[belong[sa[i]]]){
  72. vis[belong[sa[i]]]=;
  73. ++cnt;
  74. }
  75. if(!vis[belong[sa[i-]]]){
  76. vis[belong[sa[i-]]]=;
  77. ++cnt;
  78. }
  79. }else{
  80. if(cnt>(m>>)){
  81. for(int j=; j<len; ++j){
  82. putchar(r[idx+j]+'a'-);
  83. }
  84. putchar('\n');
  85. }
  86. memset(vis,,sizeof(vis));
  87. cnt=;
  88. }
  89. }
  90. }
  91. int main(){
  92. char s[];
  93. while(~scanf("%d",&m) && m){
  94. n=;
  95. for(int i=; i<m; ++i){
  96. scanf("%s",s);
  97. for(int j=; s[j]; ++j){
  98. belong[n]=i;
  99. r[n++]=s[j]-'a'+;
  100. }
  101. r[n++]=+i;
  102. }
  103. r[--n]=;
  104. SA(r,n+,);
  105. int l=,r=;
  106. while(l<r){
  107. int mid=l+r+>>;
  108. if(isok(mid)) l=mid;
  109. else r=mid-;
  110. }
  111. if(l==) puts("?");
  112. else pnt(l);
  113. putchar('\n');
  114. }
  115. return ;
  116. }

POJ3294 Life Forms(二分+后缀数组)的更多相关文章

  1. 2018.11.28 poj3294 Life Forms(后缀数组+双指针)

    传送门 后缀数组经典题目. 我们先把所有的字符串都接在一起. 然后求出hththt数组和sasasa数组. 然后对于sasasa数组跑双指针统计答案. 如果双指针包括进去的属于不同字符串的数量达到了题 ...

  2. poj3294 Life Forms(后缀数组)

    [题目链接] http://poj.org/problem?id=3294 [题意] 多个字符串求出现超过R次的最长公共子串. [思路] 二分+划分height,判定一个组中是否包含不小于R个不同字符 ...

  3. POJ3294 Life Forms 【后缀数组】

    生命形式 时间限制: 5000MS   内存限制: 65536K 提交总数: 16660   接受: 4910 描述 你可能想知道为什么大多数外星人的生命形式与人类相似,不同的是表面特征,如身高,肤色 ...

  4. BZOJ 2946 [Poi2000]公共串 (二分+Hash/二分+后缀数组/后缀自动机)

    求多串的最长公共字串. 法1: 二分长度+hash 传送门 法2: 二分+后缀数组 传送门 法3: 后缀自动机 拿第一个串建自动机,然后用其他串在上面匹配.每次求出SAM上每个节点的最长匹配长度后,再 ...

  5. POJ 3294 Life Forms(后缀数组+二分答案)

    [题目链接] http://poj.org/problem?id=3294 [题目大意] 求出在至少在一半字符串中出现的最长子串. 如果有多个符合的答案,请按照字典序输出. [题解] 将所有的字符串通 ...

  6. HDU4080 Stammering Aliens(二分 + 后缀数组)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4080 Description Dr. Ellie Arroway has establish ...

  7. HDU5853 Jong Hyok and String(二分 + 后缀数组)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5853 Description Jong Hyok loves strings. One da ...

  8. 【HDU 5030】Rabbit's String (二分+后缀数组)

    Rabbit's String Problem Description Long long ago, there lived a lot of rabbits in the forest. One d ...

  9. POJ-3294-Life Forms(后缀数组-不小于 k 个字符串中的最长子串)

    题意: 给定 n 个字符串,求出现在不小于 k 个字符串中的最长子串. 分析: 将 n 个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开,求后缀数组. 然后二分答案,将后缀分成若干组,判断 ...

随机推荐

  1. Python网络编程(weekly summary1)

    网络的目的是什么?     用于信息传输.接受  能把各个点.面.体的信息链接到一起 实现资源的共享 OSI模型:     应用层:提供程序服务     表示层:数据加密.优化.压缩     会话层: ...

  2. 孤荷凌寒自学python第四十四天Python操作 数据库之准备工作

     孤荷凌寒自学python第四十四天Python操作数据库之准备工作 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天非常激动地开始接触Python的数据库操作的学习了,数据库是系统化设计 ...

  3. crmsh语法

    .查看配置信息 crm(live)# configure crm(live)configure# show node node1 node node2 property cib-bootstrap-o ...

  4. 1020 Tree Traversals (25 分)(二叉树的遍历)

    给出一个棵二叉树的后序遍历和中序遍历,求二叉树的层序遍历 #include<bits/stdc++.h> using namespace std; ; int in[N]; int pos ...

  5. 软工实践Alpha冲刺(5/10)

    队名:起床一起肝活队 组长博客:博客链接 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过去两天完成了哪些任务 描述: 已经解决登录注册等基本功能的界面. 完成了主界面的基本布局 ...

  6. Linux自学系列 -- 常用指令的使用

    1.查看目录下内容>ls //列出目录下的文件信息>ls -l      //以“详细信息"查看目录文件>ls -a     //查看目录“全部”(包括隐藏文件)文件> ...

  7. J2EE的十三个技术——EJB之消息驱动JMS

    JMS--Java Message Service JAVA的消息服务,消息可实现两端通信. 用于访问面向消息中间件的标准api,他提供与厂商无关的访问方法,以访问消息收发服务. 特点:即使其中一方不 ...

  8. 在LinkedIn的 Kafka 生态系统

    在LinkedIn的 Kafka 生态系统 Apache Kafka是一个高度可扩展的消息传递系统,作为LinkedIn的中央数据管道起着至关重要的作用. Kafka 是在2010年在LinkedIn ...

  9. BZOJ3238 [Ahoi2013]差异 【后缀数组 + 单调栈】

    题目链接 BZOJ3238 题解 简单题 经典后缀数组 + 单调栈套路,求所有后缀\(lcp\) #include<iostream> #include<cstdio> #in ...

  10. 《c程序设计语言》读书笔记-5.9-指针转换天数和日期

    #include "stdio.h" #include "stdlib.h" #include "string.h" static char ...