Life Forms
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 12483   Accepted: 3501

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 ? 瘠薄
 #include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
#define maxn 200005
int ws[maxn],wa[maxn],sa[maxn],num[maxn],n,wv[maxn],rank[maxn];
int h[maxn],wb[maxn],sum[maxn],m;
char str[][];
bool cmp(int *r,int a,int b,int l){
return r[a]==r[b]&&r[a+l]==r[b+l];
} void da(int *r,int *sa,int n,int m){
int *t,*x=wa,*y=wb,i,j,p;
for (i=;i<m;i++) ws[i]=;
for (i=;i<n;i++) x[i]=r[i];
for (i=;i<n;i++) ws[x[i]]++;
for (i=;i<m;i++) ws[i]+=ws[i-];
for (i=n-;i>=;i--) sa[--ws[x[i]]]=i;
for (j=,p=;p<n;j*=,m=p){
for (p=,i=n-j;i<n;i++) y[p++]=i;
for (i=;i<n;i++) if (sa[i]-j>=) y[p++]=sa[i]-j;
for (i=;i<m;i++) ws[i]=;
for (i=;i<n;i++) wv[i]=x[y[i]];
for (i=;i<n;i++) ws[wv[i]]++;
for (i=;i<m;i++) ws[i]+=ws[i-];
for (i=n-;i>=;i--) sa[--ws[wv[i]]]=y[i];
for (t=x,x=y,y=t,i=,p=,x[sa[]]=;i<n;i++)
x[sa[i]]=cmp(y,sa[i],sa[i-],j)?p-:p++;
}
}
void cal(int *r,int n){
int i,j,k=;
for (int i=;i<=n;i++) rank[sa[i]]=i;
for (int i=;i<n;h[rank[i++]]=k)
for (k?k--:,j=sa[rank[i]-];r[i+k]==r[j+k];k++);
}
int getid(int k){
int l=,r=n-,mid;
while (l<r){
mid=(l+r)/;
if (sum[mid]<k) {
l=mid+;
}
else
r=mid;
}
return l;
} bool check(int len,int out=){
int i=n+,j,k,id,cnt;
bool f[maxn];
while (){
while (i<=m&&h[i]<len) i++;
if (i>m) break;
memset(f,,sizeof f);
id=getid(sa[i-]);
f[id]=true;
cnt=;
while (i<=m&&h[i]>=len){
id=getid(sa[i]);
if (!f[id]){
f[id]=true;
cnt++;
}
i++;
}
if (out==){
if (*cnt>n) return true;
}
else
if (*cnt>n){
for (k=sa[i-],j=;j<len;k++,j++){
printf("%c",num[k]+'a'-);
}
printf("\n");
} }
return false;
}
int main(){
freopen("tx.in","r",stdin);
int i,j,k;
while (scanf("%d",&n)&&n!=){
scanf("%s",str[]);
if (n==){
printf("%s\n\n",str[]);
continue;
}
sum[]=strlen(str[]);
for (i=;i<n;i++){
scanf("%s",str[i]);
sum[i]=sum[i-]+strlen(str[i])+;
}
for (k=i=;i<n;i++){
for (j=;j<strlen(str[i]);j++){
num[k++]=str[i][j]-'a'+;
}
num[k++]=i;
}
m=k-;
da(num,sa,m+,);
cal(num,m);
int l=,r=m,mid;
while (l<r){
mid=(l+r+)/;
if (check(mid)) l=mid;
else r=mid-;
}
if (l==) printf("?\n\n");
else {
check(l,);
printf("\n");
}
}
}
后缀数组

poj3294 --Life Forms的更多相关文章

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

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

  2. POJ3294 Life Forms(后缀数组)

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

  3. poj3294 Life Forms(后缀数组)

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

  4. POJ-3294 Life Forms n个字符串中出现超过n/2次的最长子串(按字典序依次输出)

    按照以前两个字符串找两者的最长公共子串的思路类似,可以把所有串拼接到一起,这里为了避免讨论LCP跨越多个串需需要特别处理的问题用不同的字符把所有串隔开(因为char只有128位,和可能不够用,更推荐设 ...

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

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

  6. POJ3294 Life Forms 【后缀数组】

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

  7. POJ3294 Life Forms(二分+后缀数组)

    给n个字符串,求最长的多于n/2个字符串的公共子串. 依然是二分判定+height分组. 把这n个字符串连接,中间用不同字符隔开,跑后缀数组计算出height: 二分要求的子串长度,判断是否满足:he ...

  8. 【POJ3294】 Life Forms (后缀数组+二分)

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

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

    (累了,这题做了很久!) Life Forms Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 8683   Accepted ...

随机推荐

  1. Linux下cut命令用法

    1 一两句话描述一下cut命令吧! 正如其名,cut的工作就是“剪”,具体的说就是在文件中负责剪切数据用的. cut是以每一行为一个处理对象的,这种机制和sed是一样的.(关于sed的入门文章将在近期 ...

  2. AspNetPager实现真分页+多种样式

    真假分页 分页是Web应用程序中最常用到的功能之一.当从数据库中获取的记录远远超过界面承载能力的时候,使用分页可以使我们的界面更加美观,更加的用户友好.分页包括两种类型:真分页和假分页. 其中假分页就 ...

  3. Struts2配置RESULT中TYPE的参数说明

    chain           用来处理Action链,被跳转的action中仍能获取上个页面的值,如request信息.           com.opensymphony.xwork2.Acti ...

  4. .net中除去IList中的多余项

    IList<ActionInfo> tempList = new List<ActionInfo>(); IList<ActionInfo> tempActionL ...

  5. <php>PDO链接方法

    <?php //定义数据源 $dsn = "mysql:dbname=mydb;host=localhost"; //$dsn = "sqlsrv:dbname=m ...

  6. syslog_test.c 简单的syslog函数

    #cat syslog_test.c #include<stdio.h> #include<stdlib.h> #include<syslog.h> int mai ...

  7. oracle数据库 ORA-12560: 协议适配器错误

    ORA-12560:  协议适配器错误 造成ORA-12560: TNS: 协议适配器错误的问题的原因有三个: 1.监听服务没有起起来.windows平台个一如下操作:开始---程序---管理工具-- ...

  8. [RxJS] Resubscribing to a Stream with Repeat

    When you complete a stream, there’s no way to restart it, you must resubscribe. This lesson shows ho ...

  9. extern C的作用详解

    extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码.加上extern "C"后,会指示编译器这部分代码按C语言的进行编译,而不是C+ ...

  10. 新闻滚动marquee标签

    先上代码: <marquee behavior="" direction="up" onMouseOver="this.stop()" ...