Life Forms
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 12484   Accepted: 3502

Description

You may have wondered why most extraterrestrial life forms resemble humans, differing by superficial traits such as height, colour, wrinkles, ears, eyebrows and the like. A few bear no human resemblance; these typically have geometric or amorphous shapes like cubes, oil slicks or clouds of dust.

The answer is given in the 146th episode of Star Trek - The Next Generation, titled The Chase. It turns out that in the vast majority of the quadrant's life forms ended up with a large fragment of common DNA.

Given the DNA sequences of several life forms represented as strings of letters, you are to find the longest substring that is shared by more than half of them.

Input

Standard input contains several test cases. Each test case begins with 1 ≤ n ≤ 100, the number of life forms. n lines follow; each contains a string of lower case letters representing the DNA sequence of a life form. Each DNA sequence contains at least one and not more than 1000 letters. A line containing 0 follows the last test case.

Output

For each test case, output the longest string or strings shared by more than half of the life forms. If there are many, output all of them in alphabetical order. If there is no solution with at least one letter, output "?". Leave an empty line between test cases.

  1. /*
  2. POJ 3294 n个串中至少一半的串共享的最长公共子串
  3.  
  4. 求的是最长公共子串,所以考虑 二分答案len+判断
  5. 因为要判断是否为x个串共享所以对height进行分组,即height数组中各个连续≥len
  6. 的集合,然后对每个组进行判断,看书否能找到x+1个不同的来源。
  7. 满足条件就记录 子串的起始位置和长度
  8.  
  9. 1.串之间的间隔符号不能相同
  10. 2.因为有100个串,所以已经占据了0-99,所以字符串的信息转换成int的时候
  11. 必需是从100开始
  12.  
  13. hhh-2016-03-17 19:04:50
  14. */
  15. #include <algorithm>
  16. #include <cmath>
  17. #include <queue>
  18. #include <iostream>
  19. #include <cstring>
  20. #include <map>
  21. #include <cstdio>
  22. #include <vector>
  23. #include <functional>
  24. #define lson (i<<1)
  25. #define rson ((i<<1)|1)
  26. using namespace std;
  27. typedef long long ll;
  28. const int maxn = 101000;
  29.  
  30. int t1[maxn],t2[maxn],c[maxn];
  31. bool cmp(int *r,int a,int b,int l)
  32. {
  33. return r[a]==r[b] &&r[l+a] == r[l+b];
  34. }
  35.  
  36. void get_sa(int str[],int sa[],int Rank[],int height[],int n,int m)
  37. {
  38. n++;
  39. int p,*x=t1,*y=t2;
  40. for(int i = 0; i < m; i++) c[i] = 0;
  41. for(int i = 0; i < n; i++) c[x[i] = str[i]]++;
  42. for(int i = 1; i < m; i++) c[i] += c[i-1];
  43. for(int i = n-1; i>=0; i--) sa[--c[x[i]]] = i;
  44. for(int j = 1; j <= n; j <<= 1)
  45. {
  46. p = 0;
  47. for(int i = n-j; i < n; i++) y[p++] = i;
  48. for(int i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i]-j;
  49. for(int i = 0; i < m; i++) c[i] = 0;
  50. for(int i = 0; i < n; i++) c[x[y[i]]]++ ;
  51. for(int i = 1; i < m; i++) c[i] += c[i-1];
  52. for(int i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
  53.  
  54. swap(x,y);
  55. p = 1;
  56. x[sa[0]] = 0;
  57. for(int i = 1; i < n; i++)
  58. x[sa[i]] = cmp(y,sa[i-1],sa[i],j)? p-1:p++;
  59. if(p >= n) break;
  60. m = p;
  61. }
  62. int k = 0;
  63. n--;
  64. for(int i = 0; i <= n; i++)
  65. Rank[sa[i]] = i;
  66. for(int i = 0; i < n; i++)
  67. {
  68. if(k) k--;
  69. int j = sa[Rank[i]-1];
  70. while(str[i+k] == str[j+k]) k++;
  71. height[Rank[i]] = k;
  72. }
  73. }
  74.  
  75. int Rank[maxn];
  76. int sa[maxn];
  77. int str[maxn],height[maxn];
  78. char s[1010];
  79. char allstr[maxn];
  80. int anslen,anspos[maxn];
  81. int ansnum,vis[110];
  82. int id[maxn];
  83.  
  84. bool judge(int len,int k,int n,int l,int r)
  85. {
  86. int num = 0;
  87. memset(vis,0,sizeof(vis));
  88. for(int i = l; i <= r; i++)
  89. {
  90. if(height[i] >= len)
  91. {
  92. if(!vis[id[sa[i-1]]])
  93. {
  94. vis[id[sa[i-1]]] = 1;
  95. num ++;
  96. }
  97. if(!vis[id[sa[i]]])
  98. {
  99. vis[id[sa[i]]] = 1;
  100. num ++;
  101. }
  102. if(num > k)
  103. return 1;
  104. }
  105. }
  106. return 0;
  107. }
  108.  
  109. bool can(int len,int k,int n)
  110. {
  111. int l=2,r=2;
  112. int flag = 0;
  113. ansnum = 0;
  114. for(int i = 2; i <= n; i++)
  115. {
  116. if(height[i]>=len)
  117. r++;
  118. else
  119. {
  120. if(judge(len,k,n,l,r))
  121. {
  122. anspos[ansnum++] = sa[l];
  123. flag =1;
  124. }
  125. l = i,r = i;
  126. }
  127. }
  128. if(judge(len,k,n,l,r) && l < r)
  129. {
  130. anspos[ansnum++] = sa[l];
  131. flag =1;
  132. }
  133. return flag;
  134. }
  135.  
  136. int main()
  137. {
  138. int k,n;
  139. while(scanf("%d",&n) != EOF && n)
  140. {
  141. int len=0;
  142. int tot = 0;
  143. for(int i = 0; i< n; i++)
  144. {
  145. scanf("%s",s);
  146. for(int j = 0; s[j]!='\0'; j++)
  147. {
  148. id[tot] = i;
  149. allstr[tot] = s[j];
  150. str[tot++] = s[j]-'a'+100;
  151. }
  152. len=max(len,(int)strlen(s));
  153. id[tot] = i,allstr[tot]='$';
  154. str[tot++]=i;
  155. }
  156. str[tot] = 0;
  157. get_sa(str,sa,Rank,height,tot,128);
  158. int k = n/2;
  159. int ans = 0;
  160. int l=1,r=len;
  161. while(l <= r)
  162. {
  163. int mid =(l+r)>>1;
  164. if(can(mid,k,tot))
  165. {
  166. l = mid+1;
  167. anslen = mid;
  168. ans = ansnum;
  169. }
  170. else
  171. r = mid-1;
  172. }
  173.  
  174. if(!ans)
  175. printf("?\n");
  176. else
  177. {
  178. //cout<<ans<<endl;
  179. for(int i = 0; i < ans; i++)
  180. {
  181. for(int j = 0; j<anslen; j++)
  182. printf("%c",allstr[anspos[i]+j]);
  183. printf("\n");
  184. }
  185. }
  186. printf("\n");
  187. }
  188. return 0;
  189. }

  

POJ 3294 n个串中至少一半的串共享的最长公共子串的更多相关文章

  1. SPOJ - PHRASES Relevant Phrases of Annihilation —— 后缀数组 出现于所有字符串中两次且不重叠的最长公共子串

    题目链接:https://vjudge.net/problem/SPOJ-PHRASES PHRASES - Relevant Phrases of Annihilation no tags  You ...

  2. POJ 3294 Life Forms [最长公共子串加强版 后缀数组 && 二分]

    题目:http://poj.org/problem?id=3294 Life Forms Time Limit: 5000MS   Memory Limit: 65536K Total Submiss ...

  3. 字符串hash + 二分答案 - 求最长公共子串 --- poj 2774

    Long Long Message Problem's Link:http://poj.org/problem?id=2774 Mean: 求两个字符串的最长公共子串的长度. analyse: 前面在 ...

  4. 后缀数组(模板题) - 求最长公共子串 - poj 2774 Long Long Message

    Language: Default Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 21 ...

  5. poj 2774 最长公共子串 后缀数组

    Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 25752   Accepted: 10 ...

  6. POJ 2774 Long Long Message [ 最长公共子串 后缀数组]

    题目:http://poj.org/problem?id=2774 Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total ...

  7. 「双串最长公共子串」SP1811 LCS - Longest Common Substring

    知识点: SAM,SA,单调栈,Hash 原题面 Luogu 来自 poj 的双倍经验 简述 给定两字符串 \(S_1, S_2\),求它们的最长公共子串长度. \(|S_1|,|S_2|\le 2. ...

  8. POJ 2217 (后缀数组+最长公共子串)

    题目链接: http://poj.org/problem?id=2217 题目大意: 求两个串的最长公共子串,注意子串是连续的,而子序列可以不连续. 解题思路: 后缀数组解法是这类问题的模板解法. 对 ...

  9. SPOJ 1811 Longest Common Substring (后缀自动机第一题,求两个串的最长公共子串)

    题目大意: 给出两个长度小于等于25W的字符串,求它们的最长公共子串. 题目链接:http://www.spoj.com/problems/LCS/ 算法讨论: 二分+哈希, 后缀数组, 后缀自动机. ...

随机推荐

  1. Python 实现队列

    操作 Queue() 创建一个空的队列 enqueue(item) 往队列中添加一个item元素 dequeue() 从队列头部删除一个元素 is_empty() 判断一个队列是否为空 size() ...

  2. Cocoapods最全完整使用教程

    什么是cocoapods cocoapods是库管理工具. cocoapods的用途 解决库之间的依赖关系.如前文所述: 一个开源的项目可能是另一个项目的基础, A依赖B, B依赖C和D, D又依赖E ...

  3. vue的简单tab

    <!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" ...

  4. unity3D 知识点随手记

    最近闲来无事,记记unity3D相关的一些知识点吧,也当作笔记存储.转载请标明出处:http://www.cnblogs.com/zblade/ 1.unity是如何调用Start/Awake等相关函 ...

  5. SpringBoot+Angular2 开发环境搭建

    https://segmentfault.com/a/1190000007921675

  6. apollo1.7.1初探(一)安装apollo、创建并启动broker

    Apache Apollo是一个代理服务器,是在ActiveMQ基础上发展而来的,支持STOMP, AMQP, MQTT, Openwire, SSL, and WebSockets 等多种协议. A ...

  7. NHibernate的基本使用

    一.O/R Mapping 概论 工厂模式+反射+每个数据库的DAL层来解决数据访问层的代码 针对数据库表中字段的变化我们是无法预料的,所以每一次用户需求的修改都会直接导致我们程序员来修改—实体类(B ...

  8. Swing使用JavaFXweb组件

    概述 swing中内嵌入web组件的 需要使用一些其他的jar包 ,但是如果使用javafx的组件,那么也比较的方便,性能也比较高. 代码 webview 在javafx 中是作为 scene出现的所 ...

  9. JavaScript中的单体模式四种实现方式

    /* 1 简单单体 */ var Singleton = { attr1: 1 , method1:function(){ //do sth } }; alert(Singleton.attr1); ...

  10. python中两种方法实现二分法查找,细致分析二分法查找算法

    之前分析了好多排序算法,可难理解了呢!!(泣不成声)这次我要把二分查找总结一下,这个算法不算难度特别大,欢迎大家参考借鉴我不喜欢太官方的定义,太晦涩的语言,让人看了就头晕.我希望加入我自己的理解,能帮 ...