Life Forms
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 13063   Accepted: 3670

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以上1次数的公共子串。
 
思路:
将所有的子串连起来,中间用没有出现过的符号隔开(不过要注意的是,不能通过s[i] + 某个值来处理,因为ascill码中知道127,在加的话会先加成字符,由于大于127可能会乱码,这样其实给r[]的时候,值是不对的。
还有就是我写的时候,从1开始加竟然有问题,也不清楚为什么。)。然后二分长度(也就是答案),枚举判断复合长度的后缀,因为每一个字符串只能提供一个子串,所以我们要判断这个子串在哪一个字符串中(换一句话说 在每一组height中 每个字符串只能给你一个子串)。最后存一下答案就ok了。
 
/*
* Author: sweat123
* Created Time: 2016/7/10 22:01:18
* File Name: main.cpp
*/
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<string>
#include<vector>
#include<cstdio>
#include<time.h>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 1<<30
#define MOD 1000000007
#define ll long long
#define lson l,m,rt<<1
#define key_value ch[ch[root][1]][0]
#define rson m+1,r,rt<<1|1
#define pi acos(-1.0)
using namespace std;
const int MAXN = ;
char s[][];
int n,m,wa[MAXN],wb[MAXN],wc[MAXN],r[MAXN],height[MAXN],Rank[MAXN],sa[MAXN];
int a[],cnt,vis[];
void da(int *r,int *sa,int n,int m){
int *x = wa,*y = wb;
for(int i = ; i < m; i++)wc[i] = ;
for(int i = ; i < n; i++)wc[x[i] = r[i]] ++;
for(int i = ; i < m; i++)wc[i] += wc[i-];
for(int i = n - ; i >= ; i--)sa[--wc[x[i]]] = i;
for(int p = ,k = ; p < n; k <<= , m = p){
p = ;
for(int i = n - k; i < n; i++)y[p++] = i;
for(int i = ; i < n; i++)if(sa[i] >= k)y[p++] = sa[i] - k;
for(int i = ; i < m; i++)wc[i] = ;
for(int i = ; i < n; i++)wc[x[y[i]]] ++;
for(int i = ; i < m; i++)wc[i] += wc[i-];
for(int i = n - ; i >= ; i--)sa[--wc[x[y[i]]]] = y[i];
swap(x,y);
p = ;
x[sa[]] = ;
for(int i = ; i < n; i++){
x[sa[i]] = (y[sa[i]] == y[sa[i-]] && y[sa[i]+k] == y[sa[i-]+k])?p-:p++;
}
}
}
void calheight(int *r,int *sa,int n){
for(int i = ; i <= n; i++)Rank[sa[i]] = i;
int j,k;
k = ;
for(int i = ; i < n; height[Rank[i++]] = k){
for(k?k--:,j = sa[Rank[i] - ]; r[i+k] == r[j+k]; k++);
}
}
int find(int x){
int l,r,m,ans;
l = ,r = cnt - ;
while(l <= r){
m = (l + r) >> ;
if(a[m] <= x){
ans = m;
l = m + ;
} else {
r = m - ;
}
}
return ans;
}
vector<int>q;
int ok(int x,int num){
int ans = ;
q.clear();
memset(vis,,sizeof(vis));
for(int i = ; i <= n; i++){
if(height[i] >= x){
int tp1 = find(sa[i-]);
int tp2 = find(sa[i]);
if(tp1 == tp2)continue;
//cout<<x<<' '<<height[i]<<' '<<tp1<<' '<<tp2<<' '<<sa[i]<<' '<<sa[i-1]<<' ';
//cout<<ans<<' '<<vis[tp1]<<' '<<vis[tp2]<<endl;
if(tp1 < || tp2 < )cout<<<<endl;
if(!vis[tp1]){
ans += ;
vis[tp1] = ;
}
if(!vis[tp2]){
ans += ;
vis[tp2] = ;
}
} else {
if(ans > num / ){
q.push_back(sa[i-]);
ans = ;
memset(vis,,sizeof(vis));
} else{
ans = ;
memset(vis,,sizeof(vis));
}
}
}
if(ans > num / ){
q.push_back(sa[n]);
}
if(q.size() > )return ;
return ;
}
void solve(int num){
memset(vis,,sizeof(vis));
int fl,fr,m,ans = -;
fl = ,fr = n;
while(fl <= fr){
m = (fl + fr) >> ;
if(ok(m,num)){
ans = m;
fl = m + ;
} else {
fr = m - ;
}
}
if(ans <= ){
printf("?\n");
return ;
}
ok(ans,num);
for(int i = ; i < q.size(); i++){
for(int j = ; j < ans; j++){
printf("%c",r[q[i] + j]);
}
printf("\n");
}
}
int main(){
while(~scanf("%d",&m)){
if(!m)break;
memset(a,,sizeof(a));
memset(sa,,sizeof(sa));
cnt = ;
a[] = -;
for(int i = ; i <= m; i++){
scanf("%s",s[i]);
}
n = ;
for(int i = ; i <= m; i++){
int len = strlen(s[i]);
for(int j = ; j < len; j++){
r[n++] = s[i][j];
}
r[n++] = + i;
a[cnt] = a[cnt - ] + len + ;
cnt += ;
}
n -= ;
r[n] = ;
da(r,sa,n+,);
calheight(r,sa,n);
solve(m);
printf("\n");
}
return ;
}

poj3294 出现次数大于n/2 的公共子串的更多相关文章

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

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

  2. 笔试算法题(30):从已排序数组中确定数字出现的次数 & 最大公共子串和最大公共序列(LCS)

    出题:在已经排序的数组中,找出给定数字出现的次数: 分析: 解法1:由于数组已经排序,所以可以考虑使用二分查找确定给定数字A的第一个出现的位置m和最后一个出现的位置n,最后m-n+1就是A出现的次数: ...

  3. 查找出现次数大于n/k的重复元素

    本文是对一篇英文论文的总结:Finding Repeated Elements.想看原文,请Google之. 这个问题的简单形式是“查找出现次数大于n/2的重复元素”.我们先从简单问题开始,然后再做扩 ...

  4. [LeetCode169]Majority Element求一个数组中出现次数大于n/2的数

    题目: Given an array of size n, find the majority element. The majority element is the element that ap ...

  5. oracle 查出一个表中字段值出现次数大于2的所有记录

    表web_order  列 name ,businesscode, a.account 周桥 18929609222 3754031157710000妙药 18929609233 3754031157 ...

  6. [算法]在数组中找到出现次数大于N/K的数

    题目: 1.给定一个整型数组,打印其中出现次数大于一半的数.如果没有出现这样的数,打印提示信息. 如:1,2,1输出1.    1,2,3输出no such number. 2.给定一个整型数组,再给 ...

  7. 在数组中寻找出现次数大于N/K的数

    给定一个int[]数组,给定一个整数k,打印所有出现次数大于N/k的数,没有的话,给出提示信息. === 核心思想:一次在数组中删除K个不同的数,不停的删除,直到剩下的数的种类不足K就停止删除,那么如 ...

  8. 《程序员代码面试指南》第八章 数组和矩阵问题 在数组中找到出现次数大于N/K 的数

    题目 在数组中找到出现次数大于N/K 的数 java代码 package com.lizhouwei.chapter8; import java.util.ArrayList; import java ...

  9. CodeForces - 840D:(主席树求出现区间出现次数大于某值的最小数)

    Once, Leha found in the left pocket an array consisting of n integers, and in the right pocket q que ...

随机推荐

  1. UVa11549计算器谜题[floyd判圈]

    题意: 有个老式计算器,每次只能记住一个数字的前n位.现在输入一个整数k,然后反复平方,一直做下去,能得到的最大数是多少.例如,n=1,k=6,那么一次显示:6,3,9,1... 白书上的题 set, ...

  2. AC日记——逆波兰表达式 openjudge 3.3 1696

    1696:逆波兰表达式 总时间限制:  1000ms 内存限制:  65536kB 描述 逆波兰表达式是一种把运算符前置的算术表达式,例如普通的表达式2 + 3的逆波兰表示法为+ 2 3.逆波兰表达式 ...

  3. 嵌入式Linux驱动学习之路(一)嵌入式系统的软硬件架构

    硬件资料: 操作系统:(非虚拟机) zws@z-pc:~$ lsb_release -aNo LSB modules are available.Distributor ID: Ubuntu Desc ...

  4. ubuntu14安装Qt

    首先下载Qt源码 https://download.qt.io/archive/qt/4.8/4.8.4/ 这里我下载的是qt-everywhere-opensource-src-4.8.4.tar. ...

  5. ApplicationWindow

    本文介绍了一个使用ApplicationWindow 和Action 实现的一个文本编辑器.界面美观,基本功能齐全.代码齐全. 首先看 MainWindow.java. //MainWindow.ja ...

  6. webpack常用加载器和插件

    css文件加载器: style-loader,css-loader,sass-loader,less-loader //style和css加载器必须放在一起使用,且style必须放前面(style!c ...

  7. IIS Enabling HTTP Keep-Alives

    IIS 6.0 from:https://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/ea116535-8e ...

  8. 事故记录:php-cgi进程过多导致系统资源耗尽

    事故现象:机房一台服务器运行一段时间后,突然发现系统资源即将被耗尽! 1)top命令查看一下系统的cpu ram swap的使用情况 由上图分析,可以看出1--共有602个进程,但其中有601个进程休 ...

  9. Python的高级特性1:容易忽略的不可变类型

    python中有一些容易忽略的不可变类型(str,integer,tuple,None) #错误演示 In [45]: def demo(lst=[]): ....: lst.append(" ...

  10. java:利用xpath删除xml中的空节点

    原始xml内容: <data> <a> </a> <b>b1</b> <awb> <awbpre>123</a ...