Life Forms

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 ?

思路

  • 后缀数组
  • 由于答案子串长度和答案个数具有单调性,可用二分答案法
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std; const int Max=501;
const int MAX=1e5+1500;
string s,ss[Max];
int n,mx;
int rnk[MAX],sa[MAX];
int tmp[MAX],c[MAX];
int h[MAX],sy[MAX]; void lcp()
{
h[0]=0;
for(int i=0,j=rnk[0],k=0; i<n-1; i++,k++)
while(k>=0&&s[i]!=s[sa[j-1]+k])
h[j]=k--,j=rnk[sa[j]+1];
} void sarank()
{
int na=256;
memset(c,0,na*sizeof(int));
n=s.size();
s[n]=1;n++;
for(int i=0; i<n; i++) rnk[i]=(int)s[i],c[rnk[i]]++;
for(int i=1; i<na; i++) c[i]=c[i]+c[i-1];
for(int i=0; i<n; i++) c[rnk[i]]--,sa[c[rnk[i]]]=i;
int j;
for(int len=1; len<n; len=len<<1)
{
for(int i=0; i<n; i++)
{
j=sa[i]-len;
if(j<0) j=j+n;
tmp[c[rnk[j]]++]=j;
}
sa[tmp[c[0]=0]]=j=0;
for(int i=1; i<n; i++)
{
if(rnk[tmp[i]]!=rnk[tmp[i-1]]||rnk[tmp[i]+len]!=rnk[tmp[i-1]+len]) c[++j]=i;
sa[tmp[i]]=j;
}
memcpy(rnk,sa,n*sizeof(int));
memcpy(sa,tmp,n*sizeof(int));
if(j>=n-1) break;
}
} int T;
bool fl[Max]; void print(int ans)
{
int tot=0,i=0;
memset(fl,false,sizeof(fl));
while(i<n)
{
tot=0;
if(h[i]>=ans)
{
while(h[i]>=ans)
{
if(!fl[sy[sa[i]]]&&sy[sa[i]]!=0&&sy[sa[i]]!=sy[sa[i-1]]) tot++,fl[sy[sa[i]]]=true;
if(!fl[sy[sa[i-1]]]&&sy[sa[i-1]]!=0&&sy[sa[i]]!=sy[sa[i-1]]) tot++,fl[sy[sa[i-1]]]=true;
i++;
}
if(tot>T/2)
{
for(int j=sa[i-1]; j<sa[i-1]+ans; j++)
cout<<s[j];
cout<<endl;
}
memset(fl,false,sizeof(fl));
}
i++;
}
} bool pd(int m)
{
int tot=0,i=1;bool f;
memset(fl,false,sizeof(fl));
while(i<n)
{
tot=0;f=false;
if(h[i]>=m)
{
while(h[i]>=m)
{
if(h[i]==m) f=true;
if(!fl[sy[sa[i]]]&&sy[sa[i]]!=0&&sy[sa[i]]!=sy[sa[i-1]]) tot++,fl[sy[sa[i]]]=true;
if(!fl[sy[sa[i-1]]]&&sy[sa[i-1]]!=0&&sy[sa[i]]!=sy[sa[i-1]]) tot++,fl[sy[sa[i-1]]]=true;
i++;
if(tot>T/2&&f) return true;
}
memset(fl,false,sizeof(fl));
}
i++;
}
return false;
} void solve()
{
int l=1,r=mx,mid,ans=0;
while(l<=r)
{
mid=(l+r)>>1;
if(pd(mid)) ans=mid,l=mid+1;
else r=mid-1;
}
if(ans) print(ans);
else printf("?\n");
} int main()
{
int sl;
bool flag=true;
while(true)
{
if(!flag) printf("\n");
else flag = false;
scanf("%d",&T);
if(T==0) break;
s="";mx=0;
for(int i=0; i<Max; i++) c[i]=h[i]=sa[i]=sy[i]=tmp[i]=rnk[i]=0;
for(int i=1; i<=T; i++)
{
cin>>ss[i];sl=ss[i].size();
for(int j=s.size(); j<s.size()+sl; j++) sy[j]=i;
s=s+ss[i]+char(i);
mx=max(mx,sl);
}
sarank(),lcp();
solve();
}
return 0;
}

Life Forms[poj3294]题解的更多相关文章

  1. 后缀数组练习4:Life Forms

    有一个细节不是特别懂,然后的话细节有点多,就是挺难发现的那一种,感谢大佬的博客 1470: 后缀数组4:Life Forms poj3294 时间限制: 1 Sec  内存限制: 128 MB提交: ...

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

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

  3. 【POJ3294】 Life Forms (后缀数组+二分)

    Life Forms Description You may have wondered why most extraterrestrial life forms resemble humans, d ...

  4. poj3294 --Life Forms

    Life Forms Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 12483   Accepted: 3501 Descr ...

  5. Life Forms (poj3294 后缀数组求 不小于k个字符串中的最长子串)

    (累了,这题做了很久!) Life Forms Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 8683   Accepted ...

  6. 【poj3294】 Life Forms

    http://poj.org/problem?id=3294 (题目链接) 题意 给定 n 个字符串,求出现在不小于 k 个字符串中的最长子串. Solution 后缀数组论文题.. 将 n 个字符串 ...

  7. 【POJ3294】Life Forms(后缀数组,二分)

    题意: n<=100 len[i]<=1000 思路:这是一道论文题 ..]of longint; ch:..]of ansistring; n,n1,l,r,mid,last,i,j,m ...

  8. POJ3294 Life Forms(后缀数组)

    引用罗穗骞论文中的话: 将n 个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开,求后缀数组.然后二分答案,用和例3 同样的方法将后缀分成若干组,判断每组的后缀是否出现在不小于k 个的原串中 ...

  9. poj3294 Life Forms(后缀数组)

    [题目链接] http://poj.org/problem?id=3294 [题意] 多个字符串求出现超过R次的最长公共子串. [思路] 二分+划分height,判定一个组中是否包含不小于R个不同字符 ...

随机推荐

  1. linux 手工释放内存 高内存 内存回收 方法思路

    linux  跑的apache,apache工作模式有   Prefork.Worker和 Event  三种,分别是基于进程.线程.综合模式.        本文中使用的apache是 Event  ...

  2. 忘记centos的root用户密码怎么办?

    1 重置centos7管理员密码 1.1 重置centos7管理员密码的几个步骤 1)重启服务器后,在grub菜单界面,根据界面显示的提示信息,按 e 进入编辑模式.注意:是否开启selinux,重置 ...

  3. 杭电-------2048不容易系列之(4)考新郎(C语言)

    /* 思路:有n位新郎,但是又m位新郎会找错,那么有n-m位新郎会找对,而找对的n-m位新郎的找发就是在 n位新郎中随机找n-m位有多少种排列组合公式有n!/(m!*(n-m!)),而另外找错的新郎则 ...

  4. Vue子组件和根组件的关系

    代码: <script type="text/javascript"> const Foo = Vue.extend({ template: `<div id=& ...

  5. leetcode--js--Two Sum

    问题描述: 给定一个整数数列,找出其中和为特定值的那两个数. 你可以假设每个输入都只会有一种答案,同样的元素不能被重用. 示例: 给定 nums = [2, 7, 11, 15], target = ...

  6. 微信小程序入门笔记-使用云开发(4)

    1.云数据库 一.介绍 云开发提供了一个 JSON 数据库,顾名思义,数据库中的每条记录都是一个 JSON 格式的对象.一个数据库可以有多个集合(相当于关系型数据中的表),集合可看做一个 JSON 数 ...

  7. Git安装与配置,以及pycharm提交代码到github

    1.下载git,安装 下载好后直接下一步到底,安装成功(选择组件页面,可以勾选上控制台窗口字体选项,如下图) 2.配置Git信息 1.打开窗口中,输入:git --version 查看已安装的git版 ...

  8. redis中hash数据类型

    remoteSelf:1>hset website google "www.google.com" "1" remoteSelf:1>hget we ...

  9. Linux Samba文件共享服务,安装与案例配置

    Samba服务器安装和配置 1:安装Samba服务器软件包 [root@localhost ~]# rpm -qa | grep samba [root@localhost ~]# yum -y in ...

  10. java Reflection(反射)基础知识讲解

    原文链接:小ben马的java Reflection(反射)基础知识讲解 1.获取Class对象的方式 1.1)使用 "Class#forName" public static C ...