Life Forms[poj3294]题解
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]题解的更多相关文章
- 后缀数组练习4:Life Forms
有一个细节不是特别懂,然后的话细节有点多,就是挺难发现的那一种,感谢大佬的博客 1470: 后缀数组4:Life Forms poj3294 时间限制: 1 Sec 内存限制: 128 MB提交: ...
- POJ3294 Life Forms —— 后缀数组 最长公共子串
题目链接:https://vjudge.net/problem/POJ-3294 Life Forms Time Limit: 5000MS Memory Limit: 65536K Total ...
- 【POJ3294】 Life Forms (后缀数组+二分)
Life Forms Description You may have wondered why most extraterrestrial life forms resemble humans, d ...
- poj3294 --Life Forms
Life Forms Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 12483 Accepted: 3501 Descr ...
- Life Forms (poj3294 后缀数组求 不小于k个字符串中的最长子串)
(累了,这题做了很久!) Life Forms Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 8683 Accepted ...
- 【poj3294】 Life Forms
http://poj.org/problem?id=3294 (题目链接) 题意 给定 n 个字符串,求出现在不小于 k 个字符串中的最长子串. Solution 后缀数组论文题.. 将 n 个字符串 ...
- 【POJ3294】Life Forms(后缀数组,二分)
题意: n<=100 len[i]<=1000 思路:这是一道论文题 ..]of longint; ch:..]of ansistring; n,n1,l,r,mid,last,i,j,m ...
- POJ3294 Life Forms(后缀数组)
引用罗穗骞论文中的话: 将n 个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开,求后缀数组.然后二分答案,用和例3 同样的方法将后缀分成若干组,判断每组的后缀是否出现在不小于k 个的原串中 ...
- poj3294 Life Forms(后缀数组)
[题目链接] http://poj.org/problem?id=3294 [题意] 多个字符串求出现超过R次的最长公共子串. [思路] 二分+划分height,判定一个组中是否包含不小于R个不同字符 ...
随机推荐
- C语言基础五 数组
数组跟变量的区别? 数组是可以在内存中连续存储多个元素的结构,所有元素必须属于相同类型. 格式:元素类型 数组名[元素个数]: 数组的特点: 只能存放单一元素的数据,里面存放的数据成为元素. 数组的声 ...
- StackExchange.Redis 之 Set集合 类型示例
话不多说直接上代码: // set添加单个元素 stopwatch.Start(); "); stopwatch.Stop(); Console.WriteLine("set添加单 ...
- Spark之RDD本质
1.在一个完整的数据转换流程里往往涉及到多个具有衍生关系RDD,这些RDD其实是通过逻辑串联来利用装饰器模式层层包装扩展的的一堆对象,这些相邻RDD间必须有继承关系.并且比Java中的装饰器来的更彻底 ...
- 回到未来:Smalltalk 编程系统
Smalltalk 是19世纪70年代由 Alan Kay 设计的,第一个以面向对象(Object-Orientation)为主要范式的编程语言 1.Smalltalk 具有大量首创的特性,深刻影响了 ...
- css3新增边框、阴影、边框、背景、文本、字体
css3和css有什么区别?简单来讲css3是css(层叠样式表)技术的升级版本,css3新特征有很多,例如圆角效果.图形化边界.块阴影与文字阴影.使用RGBA实现透明效果.渐变效果.使用@Font- ...
- 使用 Apache James 3.3.0(开源免费) 搭建外网电子邮件服务器(基于 Windows + Amazon Corretto 8)
对于邮件服务器的安装,请先参阅: 使用 Apache James 3.3.0(开源免费) 搭建内网电子邮件服务器(基于 Windows + Amazon Corretto 8) https://www ...
- MySQL保存微信昵称中的特殊符号造成:(Incorrect string value: "xxxx'for column ‘name’ at row 1)异常
今天有业务员反应,编辑某个用户的信息的时候出现了异常,异常信息如下: Incorrect string value: "xFOx9Fx92x9D vxE6..'f or column 'na ...
- xcode 11.3 发布ipa采坑记录
为了适配ios13,特意更新了xcode11.3 .更新完后发现 application loader没有了,然后蒙了. 然后网上一顿搜索,归纳出了三种上传方式: 一.altool 使用xcode中的 ...
- VBA操作IE
1.参照项目 Microsoft Internet Controls Microsoft HTML Object 2.sample Sub GetIEItem() Dim objIE As ...
- oracle分组后取最新的记录
使用Group By来实现取最新记录,需要注意一个问题,如果最大时间相同的数据都会被取出来. PS:即使数据字段类型是timestamp,也会登录相同的时间的数据. select A.* from A ...