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. HTML标签----图文详解(二)

    HTML标签超详细的图文演示再来一波~~~ 如果还没有看过昨天的福利的,那可要抓紧喽,传送门:HTML标签----图文详解 本文主要内容 列表标签 表格标签 框架标签及内嵌框架<iframe&g ...

  2. BZOJ4152The Captain[DIjkstra]

    4152: [AMPPZ2014]The Captain Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 700  Solved: 266[Submit ...

  3. java 22 - 4 多线程的代码实现的方式1

    需求:我们要实现多线程的程序. 如何实现呢? 由于线程是依赖进程而存在的,所以我们应该先创建一个进程出来. 而进程是由系统创建的,所以我们应该去调用系统功能创建一个进程. Java是不能直接调用系统功 ...

  4. ubuntu下解析udt数据包

    udt是通过udp进行端到端可靠传输的一个协议,有其默认拥塞控制算法. 之前ubuntu下wireshark的版本是1.10,不能直接解析udt数据包[1],升级到最新的2.0.0即可过滤udt数据包 ...

  5. 应用多个icon的对比

    在给应用设计图标的时候,可能会遇到这样的需求,应用图标有老版和新版两种,而又想在桌面上同时显示这两个图标以对比效果. 一个应用本身只有一个自己的icon,在AndroidManifest.xml文件中 ...

  6. Centos6.5 设置nfs

    安装 rpcbind 和 nfs-utils yum install rpcbind yum install nfs-utils 设置共享目录 [root@bogon ~]# vim /etc/exp ...

  7. Java 集合系列05之 LinkedList详细介绍(源码解析)和使用示例

    概要  前面,我们已经学习了ArrayList,并了解了fail-fast机制.这一章我们接着学习List的实现类——LinkedList.和学习ArrayList一样,接下来呢,我们先对Linked ...

  8. CSS3 perspecitve属性

    M M .div1 { position: relative; height: 150px; width: 150px; margin: 0px; padding:2px; border: 1px s ...

  9. mybatis 3.2.8 + log4j2.0.2 控制台输出sql语句

    mybatis3.2.7有一个bug,使用log4j2 (2.0.2)版本时,会找不到类 ,导致启动失败,详见 https://github.com/mybatis/mybatis-3/issues/ ...

  10. 【算法之美】你可能想不到的归并排序的神奇应用 — leetcode 327. Count of Range Sum

    又是一道有意思的题目,Count of Range Sum.(PS:leetcode 我已经做了 190 道,欢迎围观全部题解 https://github.com/hanzichi/leetcode ...