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. div根据内容改变大小并且左右居中

    div{ display:inline-block; width:auto; } 这个div的父元素text-align:center;

  2. SpringMVC讲解

    2.1.Spring Web MVC是什么 Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职 ...

  3. 逗号分隔的字符串转换为行数据(collection)

    逗号分隔的字符串转换为行数据(collection) CREATE OR REPLACE FUNCTION "GET_STR_TAB" (v_str in varchar2) re ...

  4. fiddler和xampp安装成功后,网站打不开的原因

    fiddler和xampp安装成功后,网站打不开,出现403的错误 解决办法 编辑httpd.conf文件注释掉以下代码 #AllowOverride none # Require all denie ...

  5. 配置Tomcat使用Redis作为session管理

    1. 在 tomcat/lib 中增加以下jar包 commons-pool2-.jar jedis-.jar tomcat-redis-session-manager-.jar 2. 修改tomca ...

  6. 01Spring_基本jia包的导入andSpring的整体架构and怎么加入日志功能

    1.什么是Spring : v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:u ...

  7. Exchange WebSerivce Usage

    //ExchangeService版本为2007SP1 ExchangeService service = new ExchangeService(ExchangeVersion.Exchange20 ...

  8. jboss的时区问题

    默认情况下,jboss启动时,使用的时区是“+0:00”区,而中国所在的时间为"+8:00"区(所谓的东8区),最终java取当前时间时,总比北京时间慢8个小时 解决办法: 新建一 ...

  9. tkinter 的两个例子

    第一个例子:after 用于定时操作 import tkinter as tk import time class MyApp(tk.Frame): def __init__(self, msecs= ...

  10. npm中package.json详解

    通常我们使用npm init命令来创建一个npm程序时,会自动生成一个package.json文件.package.json文件会描述这个NPM包的所有相关信息,包括作者.简介.包依赖.构建等信息,格 ...