Life Forms

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.

Sample Input

3
abcdefg
bcdefgh
cdefghi
3
xxx
yyy
zzz
0

Sample Output

bcdefg
cdefgh ?



【题意】

  给定n个字符串,求出现在大于n/2个字符串中的最长子串。

【分析】

  把n个串拼起来,中间插入不同的特殊字符(注意要不同的)。然后求height数组。

  二分答案,根据二分的L分组,统计组内有多少个来自不同的串即可。

  最后输出的字符串要按字典序,不过不用排序,因为求出的sa表示它已经排好序了,所以就按照顺序输入就好了。

  傻逼的我RE了很久竟然是数组大小开的混乱~~呵呵~~

代码如下:

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define Maxn 410
#define Maxl 4010
#define Ml 400010 int c[Ml];
int n,cl; char s[Maxl];
int p[Ml];
void init()
{
cl=;
for(int i=;i<=n;i++)
{
scanf("%s",s);
int l=strlen(s);
for(int j=;j<l;j++) c[++cl]=s[j]-'a'+,p[cl]=i;
c[++cl]=+i,p[cl]=;
}
} int sa[Ml],rk[Ml],Rs[Ml],y[Ml],wr[Ml];
void get_sa(int m)
{
memcpy(rk,c,sizeof(rk));
for(int i=;i<=m;i++) Rs[i]=;
for(int i=;i<=cl;i++) Rs[rk[i]]++;
for(int i=;i<=m;i++) Rs[i]+=Rs[i-];
for(int i=cl;i>=;i--) sa[Rs[rk[i]]--]=i; int ln=,p=;//p表示目前有多少个不一样的rk
while(p<cl)
{
int k=;
for(int i=cl-ln+;i<=cl;i++) y[++k]=i;
for(int i=;i<=cl;i++) if(sa[i]>ln) y[++k]=sa[i]-ln;
for(int i=;i<=cl;i++) wr[i]=rk[y[i]]; for(int i=;i<=m;i++) Rs[i]=;
for(int i=;i<=cl;i++) Rs[wr[i]]++;
for(int i=;i<=m;i++) Rs[i]+=Rs[i-];
for(int i=cl;i>=;i--) sa[Rs[wr[i]]--]=y[i]; for(int i=;i<=cl;i++) wr[i]=rk[i];
for(int i=cl+;i<=cl+ln;i++) wr[i]=;
p=,rk[sa[]]=;
for(int i=;i<=cl;i++)
{
if(wr[sa[i]]!=wr[sa[i-]]||wr[sa[i]+ln]!=wr[sa[i-]+ln]) p++;
rk[sa[i]]=p;
}
ln*=;m=p;
}
sa[]=rk[]=;
} int height[Ml];
void get_he()
{
int k=;
for(int i=;i<=cl;i++) if(rk[i]!=)
{
int j=sa[rk[i]-];
if(k) k--;
while(c[i+k]==c[j+k]&&i+k<=cl&&j+k<=cl) k++;
height[rk[i]]=k;
}
} bool inq[Maxn];
queue<int > q;
int ans[][Ml],now;
bool check(int x)
{
if(x==) return ;
ans[-now][]=;
int cnt=;
bool ok=;
for(int i=;i<=cl-n;i++)
{
if(!inq[p[sa[i]]])
{
q.push(p[sa[i]]);
inq[p[sa[i]]]=;
cnt++;
}
if(height[i+]<x)//new group
{
if(cnt>n/&&cnt!=) ok=,ans[-now][++ans[-now][]]=sa[i];
cnt=;
while(!q.empty()) {inq[q.front()]=;q.pop();}
}
}
if(ok) now=-now;
return ok;
} void ffind()
{
now=;
while(!q.empty()) q.pop();
memset(inq,,sizeof(inq));
int l=,r=cl;
while(l<r)
{
int mid=(l+r+)>>;
if(check(mid)) l=mid;
else r=mid-;
}
if(l==) printf("?\n");
else
{
for(int i=;i<=ans[now][];i++)
{
for(int j=;j<l;j++)
printf("%c",c[j+ans[now][i]]-+'a');
printf("\n");
}
}
} int main()
{
while()
{
scanf("%d",&n);
if(n==) break;
init();
get_sa(+n);
get_he();
ffind();
printf("\n");
}
return ;
} [POJ3294]

[POJ3294]

2016-07-18 11:04:28


												

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

  1. POJ3294 Life Forms —— 后缀数组 最长公共子串

    题目链接:https://vjudge.net/problem/POJ-3294 Life Forms Time Limit: 5000MS   Memory Limit: 65536K Total ...

  2. Poj 3294 Life Forms (后缀数组 + 二分 + Hash)

    题目链接: Poj 3294 Life Forms 题目描述: 有n个文本串,问在一半以上的文本串出现过的最长连续子串? 解题思路: 可以把文本串用没有出现过的不同字符连起来,然后求新文本串的heig ...

  3. POJ3294 Life Forms(后缀数组)

    引用罗穗骞论文中的话: 将n 个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开,求后缀数组.然后二分答案,用和例3 同样的方法将后缀分成若干组,判断每组的后缀是否出现在不小于k 个的原串中 ...

  4. POJ3294--Life Forms 后缀数组+二分答案 大于k个字符串的最长公共子串

                                                                              Life Forms Time Limit: 500 ...

  5. POJ 3294 Life Forms 后缀数组+二分 求至少k个字符串中包含的最长子串

    Life Forms   Description You may have wondered why most extraterrestrial life forms resemble humans, ...

  6. poj 3294 Life Forms - 后缀数组 - 二分答案

    题目传送门 传送门I 传送门II 题目大意 给定$n$个串,询问所有出现在严格大于$\frac{n}{2}$个串的最长串.不存在输出'?' 用奇怪的字符把它们连接起来.然后求sa,hei,二分答案,按 ...

  7. BZOJ 3230: 相似子串( RMQ + 后缀数组 + 二分 )

    二分查找求出k大串, 然后正反做后缀数组, RMQ求LCP, 时间复杂度O(NlogN+logN) -------------------------------------------------- ...

  8. BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案

    BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案 Description          给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l        读入单 ...

  9. 【bzoj4310】跳蚤 后缀数组+二分

    题目描述 很久很久以前,森林里住着一群跳蚤.一天,跳蚤国王得到了一个神秘的字符串,它想进行研究. 首先,他会把串分成不超过 k 个子串,然后对于每个子串 S,他会从S的所有子串中选择字典序最大的那一个 ...

  10. BZOJ 1717 [USACO06DEC] Milk Patterns (后缀数组+二分)

    题目大意:求可重叠的相同子串数量至少是K的子串最长长度 洛谷传送门 依然是后缀数组+二分,先用后缀数组处理出height 每次二分出一个长度x,然后去验证,在排序的后缀串集合里,有没有连续数量多于K个 ...

随机推荐

  1. PureMVC(JS版)源码解析(十):Controller类

          这篇博客我们继续讲解PureMVC的三大核心类(View/Controller/Model)——Controller类.根据PureMVC模块设计,Controller类保存所有的Comm ...

  2. RTB日志分析MR程序设计

    到新公司三个月了,上个月做的是Beacon项目,详细的设计思想还没有写文档.这两周开始搞Hadoop,开始阅读相关论文.开始编写MR程序.开始写java,大学时用java较多,工作后就一直在用c/c+ ...

  3. 分分钟解决iOS开发中App启动广告的功能

    前不久有朋友需要一个启动广告的功能,我说网上有挺多的,他说,看的不是很理想.想让我写一个,于是乎,抽空写了一个,代码通俗易懂,简单的封装了一下,各种事件用block回调的,有俩种样式的广告,一种是全屏 ...

  4. 调试php的soapCient

    try { import('@.Ext.xml'); header("Content-Type:text/html; charset=utf-8"); $soap = new So ...

  5. opencv多平台环境搭建及使用

    windows平台: 一.安装opencv 下载地址:http://opencv.org/ 依据平台下载相应源码包 安装流程就是一个解压过程.不再赘述. 解压完,效果图: 源码树结构参看http:// ...

  6. ASCII 码表对照

    ASCII码表 ASCII码大致可以分作三部分组成.第一部分是:ASCII非打印控制字符第二部分是:ASCII打印字符:第三部分是:扩展ASCII打印字符 第一部分:ASCII非打印控制字符表 ASC ...

  7. delphi 编写一个dos 窗体

    + //dos 仿真程序 delphi 窗体实现!   function GetDosOutput(CommandLine: string; Work: string = 'C:\'): string ...

  8. (二)Struts2 核心知识

    所有的学习我们必须先搭建好Struts2的环境(1.导入对应的jar包,2.web.xml,3.struts.xml) 第一节:Struts2 get/set 自动获取/设置数据 action代码: ...

  9. tomcat环境变量配置

    先下载tomcat的压缩包(绿色版),解压到C盘目录下即可. 在系统坏境中配置(高级系统设置>环境变量>系统变量) 新建变量名:CATALINA_HOME,变量值:C:\apache-to ...

  10. OC相关-02:oc和c的基本差异

    前言: 面向过程和面向对象. 简单的说,面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用. 面向对象是把构成问题事务分解成各个对象,建立对象的目的不 ...