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. jQuery UI常用插件使用

    一.什么是插件 ①是遵循一定接口规范编写的程序 ②是原有系统平台功能的扩展和补充 ③只能运行在规定的系统平台下,而不能单独运行 注:由于jQuery插件是基于jQuery脚本库的扩展,所以所有jQue ...

  2. 网页缩放对 FLASH的影响

    目前新出的,和升级的浏览器,都加了页面放大功能, 这些功能是对FLASH有影响的,表现在 flash在获取stage.stageWidth时,数值会按相应比例有变化 本人在用flex4.6开发时,自定 ...

  3. Makefile规则③规则语法、依赖、通配符、目录搜寻、目标

    规则语法 通常规则的语法格式如下: TARGETS : PREREQUISITES COMMAND ... 或者: TARGETS : PREREQUISITES ; COMMAND COMMAND ...

  4. 队列Queue

    java中,Queue是Collection接口的子接口,Queue的实现类很多,如LinkedList类. 实际使用可以用LinkedList写一个Queue类,实现入队.出队.求队长.判空.打印等 ...

  5. 1002. A+B for Polynomials

    1002. A+B for Polynomials (25) This time, you are supposed to find A+B where A and B are two polynom ...

  6. top状态及其常用技巧

    看tcp状态 /bin/netstat -an|awk '/^tcp/{++S[$NF]}END{for(a in S) print a,S[a]}'   在 top 状态下,按 "shif ...

  7. matlab jet color mapping C / C++ / VC 实现

    在matlab中调用imagesc()将一幅灰阶图像以彩色显示时,默认使用的color mapping是Jet,其color bar 为: Jet的color mapping图为: Color map ...

  8. 前端见微知著工具篇:Grunt实现自动化

    转载说明 本篇文章为转载文章,来源为[前端福利]用grunt搭建自动化的web前端开发环境-完整教程,之所以转载,是因为本文写的太详细了,我很想自己来写,但是发现跳不出这篇文章的圈子,因为写的详尽,所 ...

  9. JSON拾遗

    最近开始翻<JavaScript高级程序设计>,其实很多大师级人物都推荐这本书为JavaScript入门级读物.因为第20章 JSON篇幅最小,而且以前也写过一篇JSON的总结JSON简介 ...

  10. 从零开始打造个人专属命令行工具集——yargs完全指南

    前言 使用命令行程序对程序员来说很常见,就算是前端工程师或者开发gui的,也需要使用命令行来编译程序或者打包程序 熟练使用命令行工具能极大的提高开发效率,linux自带的命令行工具都非常的有用,但是这 ...