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.

/*
POJ 3294 n个串中至少一半的串共享的最长公共子串 求的是最长公共子串,所以考虑 二分答案len+判断
因为要判断是否为x个串共享所以对height进行分组,即height数组中各个连续≥len
的集合,然后对每个组进行判断,看书否能找到x+1个不同的来源。
满足条件就记录 子串的起始位置和长度 1.串之间的间隔符号不能相同
2.因为有100个串,所以已经占据了0-99,所以字符串的信息转换成int的时候
必需是从100开始 hhh-2016-03-17 19:04:50
*/
#include <algorithm>
#include <cmath>
#include <queue>
#include <iostream>
#include <cstring>
#include <map>
#include <cstdio>
#include <vector>
#include <functional>
#define lson (i<<1)
#define rson ((i<<1)|1)
using namespace std;
typedef long long ll;
const int maxn = 101000; int t1[maxn],t2[maxn],c[maxn];
bool cmp(int *r,int a,int b,int l)
{
return r[a]==r[b] &&r[l+a] == r[l+b];
} void get_sa(int str[],int sa[],int Rank[],int height[],int n,int m)
{
n++;
int p,*x=t1,*y=t2;
for(int i = 0; i < m; i++) c[i] = 0;
for(int i = 0; i < n; i++) c[x[i] = str[i]]++;
for(int i = 1; i < m; i++) c[i] += c[i-1];
for(int i = n-1; i>=0; i--) sa[--c[x[i]]] = i;
for(int j = 1; j <= n; j <<= 1)
{
p = 0;
for(int i = n-j; i < n; i++) y[p++] = i;
for(int i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i]-j;
for(int i = 0; i < m; i++) c[i] = 0;
for(int i = 0; i < n; i++) c[x[y[i]]]++ ;
for(int i = 1; i < m; i++) c[i] += c[i-1];
for(int i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i]; swap(x,y);
p = 1;
x[sa[0]] = 0;
for(int i = 1; i < n; i++)
x[sa[i]] = cmp(y,sa[i-1],sa[i],j)? p-1:p++;
if(p >= n) break;
m = p;
}
int k = 0;
n--;
for(int i = 0; i <= n; i++)
Rank[sa[i]] = i;
for(int i = 0; i < n; i++)
{
if(k) k--;
int j = sa[Rank[i]-1];
while(str[i+k] == str[j+k]) k++;
height[Rank[i]] = k;
}
} int Rank[maxn];
int sa[maxn];
int str[maxn],height[maxn];
char s[1010];
char allstr[maxn];
int anslen,anspos[maxn];
int ansnum,vis[110];
int id[maxn]; bool judge(int len,int k,int n,int l,int r)
{
int num = 0;
memset(vis,0,sizeof(vis));
for(int i = l; i <= r; i++)
{
if(height[i] >= len)
{
if(!vis[id[sa[i-1]]])
{
vis[id[sa[i-1]]] = 1;
num ++;
}
if(!vis[id[sa[i]]])
{
vis[id[sa[i]]] = 1;
num ++;
}
if(num > k)
return 1;
}
}
return 0;
} bool can(int len,int k,int n)
{
int l=2,r=2;
int flag = 0;
ansnum = 0;
for(int i = 2; i <= n; i++)
{
if(height[i]>=len)
r++;
else
{
if(judge(len,k,n,l,r))
{
anspos[ansnum++] = sa[l];
flag =1;
}
l = i,r = i;
}
}
if(judge(len,k,n,l,r) && l < r)
{
anspos[ansnum++] = sa[l];
flag =1;
}
return flag;
} int main()
{
int k,n;
while(scanf("%d",&n) != EOF && n)
{
int len=0;
int tot = 0;
for(int i = 0; i< n; i++)
{
scanf("%s",s);
for(int j = 0; s[j]!='\0'; j++)
{
id[tot] = i;
allstr[tot] = s[j];
str[tot++] = s[j]-'a'+100;
}
len=max(len,(int)strlen(s));
id[tot] = i,allstr[tot]='$';
str[tot++]=i;
}
str[tot] = 0;
get_sa(str,sa,Rank,height,tot,128);
int k = n/2;
int ans = 0;
int l=1,r=len;
while(l <= r)
{
int mid =(l+r)>>1;
if(can(mid,k,tot))
{
l = mid+1;
anslen = mid;
ans = ansnum;
}
else
r = mid-1;
} if(!ans)
printf("?\n");
else
{
//cout<<ans<<endl;
for(int i = 0; i < ans; i++)
{
for(int j = 0; j<anslen; j++)
printf("%c",allstr[anspos[i]+j]);
printf("\n");
}
}
printf("\n");
}
return 0;
}

  

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. display属性

    display 属性规定元素应该生成的框的类型. 值 描述 none 此元素不会被显示. block 此元素将显示为块级元素,此元素前后会带有换行符. inline 默认.此元素会被显示为内联元素,元 ...

  2. git cherry-pick 整理

    git cherry-pick可以选择某一个分支中的一个或几个commit(s)来进行操作.例如,假设我们有个稳定版本的分支,叫v2.0,另外还有个开发版本的分支v3.0,我们不能直接把两个分支合并, ...

  3. EasyUI中easyui-combobox的onchange事件。

    html: <select id="cbox" class="easyui-combobox" name="dept" style=& ...

  4. New UWP Community Toolkit - DeveloperTools

    概述 UWP Community Toolkit  中有一个开发者工具集 DeveloperTools,可以帮助开发者在开发过程中进行 UI 和功能的调试,本篇我们结合代码详细讲解  Develope ...

  5. List集合就这么简单【源码剖析】

    前言 声明,本文用得是jdk1.8 前一篇已经讲了Collection的总览:Collection总览,介绍了一些基础知识. 现在这篇主要讲List集合的三个子类: ArrayList 底层数据结构是 ...

  6. WPF 自定义RadioButton样式

    一.RadioButton基本样式 RadioButton基本样式包含两种状态,这里也是使用两张图片来代替两种状态,当然你也可以通过IconFont或Path来替换这两种状态. 效果如下: 样式代码如 ...

  7. SpringBoot入门:Spring Data JPA 和 JPA(理论)

    参考链接: Spring Data JPA - Reference Documentation Spring Data JPA--参考文档 中文版 纯洁的微笑:http://www.ityouknow ...

  8. 阿里云API网关(18)请求报文和响应报文

    网关指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl 网关控制台: https ...

  9. 新概念英语(1-9)How is Ema?

    A:Hello Helen. B:Hi Steven. A:How are you today? B:I'm very well, thank you. And you? A:I'm fine tha ...

  10. SpringCloud是什么?

    参考链接: http://blog.csdn.net/forezp/article/details/70148833 一.概念定义       Spring Cloud是一个微服务框架,相比Dubbo ...