Life Forms
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 10800   Accepted: 2967

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个字符串的最长子串。 如果有多个按字典序输出。 大致思路:首先把所有字符串用不相同的一个字符隔开(用同一个字符隔开wa了好久), 这里我是用数字来隔开的。
然后依次求sa,lcp。 我们可以二分答案的长度, 对于长度x,我们可以把 后缀进行分组(lcp[i] < x时 隔开), 然后对于每一组判断有多少个字符串出现,如果大于n/2说明符合。。对于字典序就不用排序了,,因为我们就是按照sa数组来遍历lcp的。。所以直接得到的答案就是字典序从小到大。
 #include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const double eps = 1e-;
const int M = 2e6+;
int s[M];
int sa[M], tmp[M], rank[M], lcp[M], k, len;
bool cmp(int i, int j)
{
if (rank[i] != rank[j])
return rank[i] < rank[j];
else
{
int x = i+k <= len ? rank[i+k] : -;
int y = j+k <= len ? rank[j+k] : -;
return x < y;
}
}
void build_sa()
{
for (int i = ; i <= len; i++)
{
sa[i] = i;
rank[i] = i < len ? s[i] : -;
}
for (k = ; k <= len; k *= )
{
sort (sa, sa+len+, cmp);
tmp[sa[]] = ;
for (int i = ; i <= len; i++)
{
tmp[sa[i]] = tmp[sa[i-]] + (cmp(sa[i-], sa[i]) ? : );
}
for (int i = ; i <= len; i++)
{
rank[i] = tmp[i];
}
}
}
void Get_Lcp()
{
for (int i = ; i < len; i++)
{
rank[sa[i]] = i;
}
int h = ;
lcp[] = ;
for (int i = ; i < len; i++)
{
int j = sa[rank[i]-];
if (h > )
h--;
for (; i+h < len && j+h < len; h++)
if (s[i+h] != s[j+h])
break;
lcp[rank[i]] = h;
}
}
int vis[], pos[M];
int ans[M], tot;
int Stack[M], top;
bool solve (int x, int n)
{
int minv = inf;
int cnt = ;
bool flag = false;
for (int i = ; i <= len+; i++)
{
if (lcp[i] < x)
{ if ( cnt+ (!vis[pos[sa[i-]]]) > n/ && (minv != inf && minv >= x))
{
if (!flag )
tot = ;
flag = true;
ans[tot++] = sa[i-];
}
minv = inf;
cnt = ;
memset(vis, , sizeof (vis));
continue;
}
if ( vis[pos[sa[i-]]]==)
{
cnt++; }
vis[pos[sa[i-]]] = ;
minv = min(minv, lcp[i]); }
return tot > && flag;
}
int string_len[], c1;
void init()
{
c1 = tot = ;
memset(vis, , sizeof (vis));
memset(string_len, , sizeof (string_len));
}
char cacaca[];
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
// freopen("wa.txt","w",stdout);
#endif
int n, cas = ;
while ( scanf ("%d", &n), n)
{
if (cas != )
printf("\n");
cas++;
init();
len = ;
int del = ;
for (int i = ; i < n; i++)
{
scanf ("%s", cacaca);
int sub_len = strlen(cacaca);
for (int j = ; j < sub_len; j++)
{
s[len++] = cacaca[j];
}
s[len++] = M+del;
del++;
string_len[c1] = sub_len + string_len[c1-];
if (c1)
string_len[c1]++;
c1++;
}
if (n == )
{
for (int i = ; i < len-; i++)
{
printf("%c", s[i]);
}
continue;
}
for (int i = , j = ; i < len; i++)
{
if (i >= string_len[j])
{
pos[i] = -;
j++;
continue;
}
pos[i] = j+;
}
build_sa();
Get_Lcp(); int ua = , ub = M;
while (ua + < ub)
{
int mid = (ua + ub) >> ;
if (mid&&solve(mid, n) == true)
{ ua = mid;
}
else
ub = mid;
}
if (tot == )
printf("?\n");
else
{
if (ua == )
{
printf("?\n");
continue;
}
for (int i = ; i < tot; i++)
{
for (int j = ans[i]; j < ans[i]+ua; j++)
{
printf("%c", s[j]);
}
printf("\n");
}
}
}
return ;
}
 

POJ3294--Life Forms 后缀数组+二分答案 大于k个字符串的最长公共子串的更多相关文章

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

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

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

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

  3. 【poj3294-不小于k个字符串中最长公共子串】后缀数组

    1.注意每两个串之间的连接符要不一样. 2.分组的时候要注意最后一组啊!又漏了! 3.开数组要考虑连接符的数量.100010是不够的至少要101000. #include<cstdio> ...

  4. POJ 3080 Blue Jeans(后缀数组+二分答案)

    [题目链接] http://poj.org/problem?id=3080 [题目大意] 求k个串的最长公共子串,如果存在多个则输出字典序最小,如果长度小于3则判断查找失败. [题解] 将所有字符串通 ...

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

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

  6. Poj 1743 Musical Theme(后缀数组+二分答案)

    Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 28435 Accepted: 9604 Descri ...

  7. Poj 3261 Milk Patterns(后缀数组+二分答案)

    Milk Patterns Case Time Limit: 2000MS Description Farmer John has noticed that the quality of milk g ...

  8. POJ2774 Long Long Message —— 后缀数组 两字符串的最长公共子串

    题目链接:https://vjudge.net/problem/POJ-2774 Long Long Message Time Limit: 4000MS   Memory Limit: 131072 ...

  9. cogs249 最长公共子串(后缀数组 二分答案

    http://cogs.pro:8080/cogs/problem/problem.php?pid=pxXNxQVqP 题意:给m个单词,让求最长公共子串的长度. 思路:先把所有单词合并成一个串(假设 ...

随机推荐

  1. Android面试,与Service交互方式

    五种交互方式,分别是:通过广播交互.通过共享文件交互.通过Messenger(信使)交互.通过自定义接口交互.通过AIDL交互.(可能更多) Service与Thread的区别 Thread:Thre ...

  2. MM32 备份域学习(兼容STM32)

    MM32 备份域学习(兼容STM32) 内容提要 备份域工作原理 备份域特性 备份域的保护:侵入检测 备份域侵入检测 备份域电源与主要内容 备份域特性 20字节数据后备寄存器(中容量和小容量产品),或 ...

  3. PullToRefresh下拉刷新 加载更多 详解 +示例

    常用设置 项目地址:https://github.com/chrisbanes/Android-PullToRefresh a. 设置刷新模式 如果Mode设置成Mode.PULL_FROM_STAR ...

  4. SpringMVC06以对象的方式获取前台的数据

    ========创建需要的两个实体类================ public class School { private String sName; private String addres ...

  5. spring01

                                                                       spring的体系结构图 第一个spring入门例子 01.创建一 ...

  6. apache的500错误是写到哪个文件里面

    apache的500错误是写到哪个文件里面

  7. Installing node-oracledb on Microsoft Windows

    版本 7 由 Laura Ramsey-Oracle 于 2015-10-19 下午11:46创建,最后由 cj 于 2015-10-22 下午7:44修改. Installing node-orac ...

  8. JQuery 操作基本控件

    根据控件的样式class获取控件 $(".className")......          //className代表的就是控件的样式 根据控件的ID获取控件 $(" ...

  9. osgi与webservice

    osgi简介: http://osgia.com/ http://blog.csdn.net/xiaokui008/article/details/9662933 http://wdhdd889.it ...

  10. 安卓手机内外SD卡互换

    相信有許多人....有內置sd太小...外置sd(sdcard2或extsd)卻只能放資料.... 一些遊戲或者是影音播放軟體....根本不會去讀外置sd(sdcard2或extsd)..... 記憶 ...