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. Cocos2D-X2.2.3学习笔记12(瞬间动作)

    到眼下我们已经学习了有 坐标系统 内存管理 UI系统 事件处理 几何图形 今天我们来学习动作管理OK 我们来看看类结构图 CCAction   全部动作的基类 以下派生了三个子类:CCFiniteTi ...

  2. C#量转换为汉字表达

    /* 创造者:菜刀打好博客  * 创建日期: 2014年09一个月04号码  * 特征:Money类型转换  *  */ namespace Net.String.ConsoleApplication ...

  3. U1总结

    import java.io.Writer; import java.util.Iterator; import javax.xml.transform.TransformerFactory; imp ...

  4. 设计模式:模版模式(Template Pattern)

    android中的Activity框架,View框架中大量的on函数基本上都应用到了Template模式,掌握这一模式对于理解这些框架大有裨益. 模版模式 又叫模板方法模式,在一个方法中定义一个算法的 ...

  5. SQL Server 和CLR集成

    通过在 Microsoft SQL Server 中托管 CLR(称为 CLR 集成),可以在托管代码中编写存储过程.触发器.用户定义函数.用户定义类型和用户定义聚合函数. 因为托管代码在执行之前会编 ...

  6. timestamp 正常日期转换成时间戳格式

    select cast(sysdate as timestamp) "DATE" from dual select to_timestamp(to_date(sysdate, 'y ...

  7. Android向SDCard中上传文件时报错:Failed to push items

    向sdcard中添加文件为什么总是提示Failed to push the item(s) Failed to push XXXXX.txt on emulator-     : Read-only ...

  8. 准备开发一个基于canvas的图表库,记录一些东西(一)

    开源的图表库已经有很多了,这里从头写个自己的,主要还是 提高自己js的水平,增加复杂代码组织的经验 首先写一个画图的库,供以后画图表使用.经过2天的开发,算是能拿出点东西了,虽然功能还很弱,但是有了一 ...

  9. delphi if 语句循环语句

    if语句------------------------------------------------------------------------------------------------ ...

  10. 复杂事件处理引擎—Esper参考(事件部分)

    声明:Esper官方未提供中文文档,以后更新的大部分内容,均来自官方文档.本人英语小白一枚,翻译内容仅供参考.有些翻译确实不忍直视,君可略过. (有人可能会说,翻译的不好不如不翻,可能会误人子弟:不过 ...