【POJ3294】 Life Forms (后缀数组+二分)
Life FormsDescription
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
0Sample Output
bcdefg
cdefgh ?
【题意】
给定n个字符串,求出现在大于n/2个字符串中的最长子串。
【分析】
把n个串拼起来,中间插入不同的特殊字符(注意要不同的)。然后求height数组。
二分答案,根据二分的L分组,统计组内有多少个来自不同的串即可。
最后输出的字符串要按字典序,不过不用排序,因为求出的sa表示它已经排好序了,所以就按照顺序输入就好了。
傻逼的我RE了很久竟然是数组大小开的混乱~~呵呵~~
代码如下:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define Maxn 410
#define Maxl 4010
#define Ml 400010 int c[Ml];
int n,cl; char s[Maxl];
int p[Ml];
void init()
{
cl=;
for(int i=;i<=n;i++)
{
scanf("%s",s);
int l=strlen(s);
for(int j=;j<l;j++) c[++cl]=s[j]-'a'+,p[cl]=i;
c[++cl]=+i,p[cl]=;
}
} int sa[Ml],rk[Ml],Rs[Ml],y[Ml],wr[Ml];
void get_sa(int m)
{
memcpy(rk,c,sizeof(rk));
for(int i=;i<=m;i++) Rs[i]=;
for(int i=;i<=cl;i++) Rs[rk[i]]++;
for(int i=;i<=m;i++) Rs[i]+=Rs[i-];
for(int i=cl;i>=;i--) sa[Rs[rk[i]]--]=i; int ln=,p=;//p表示目前有多少个不一样的rk
while(p<cl)
{
int k=;
for(int i=cl-ln+;i<=cl;i++) y[++k]=i;
for(int i=;i<=cl;i++) if(sa[i]>ln) y[++k]=sa[i]-ln;
for(int i=;i<=cl;i++) wr[i]=rk[y[i]]; for(int i=;i<=m;i++) Rs[i]=;
for(int i=;i<=cl;i++) Rs[wr[i]]++;
for(int i=;i<=m;i++) Rs[i]+=Rs[i-];
for(int i=cl;i>=;i--) sa[Rs[wr[i]]--]=y[i]; for(int i=;i<=cl;i++) wr[i]=rk[i];
for(int i=cl+;i<=cl+ln;i++) wr[i]=;
p=,rk[sa[]]=;
for(int i=;i<=cl;i++)
{
if(wr[sa[i]]!=wr[sa[i-]]||wr[sa[i]+ln]!=wr[sa[i-]+ln]) p++;
rk[sa[i]]=p;
}
ln*=;m=p;
}
sa[]=rk[]=;
} int height[Ml];
void get_he()
{
int k=;
for(int i=;i<=cl;i++) if(rk[i]!=)
{
int j=sa[rk[i]-];
if(k) k--;
while(c[i+k]==c[j+k]&&i+k<=cl&&j+k<=cl) k++;
height[rk[i]]=k;
}
} bool inq[Maxn];
queue<int > q;
int ans[][Ml],now;
bool check(int x)
{
if(x==) return ;
ans[-now][]=;
int cnt=;
bool ok=;
for(int i=;i<=cl-n;i++)
{
if(!inq[p[sa[i]]])
{
q.push(p[sa[i]]);
inq[p[sa[i]]]=;
cnt++;
}
if(height[i+]<x)//new group
{
if(cnt>n/&&cnt!=) ok=,ans[-now][++ans[-now][]]=sa[i];
cnt=;
while(!q.empty()) {inq[q.front()]=;q.pop();}
}
}
if(ok) now=-now;
return ok;
} void ffind()
{
now=;
while(!q.empty()) q.pop();
memset(inq,,sizeof(inq));
int l=,r=cl;
while(l<r)
{
int mid=(l+r+)>>;
if(check(mid)) l=mid;
else r=mid-;
}
if(l==) printf("?\n");
else
{
for(int i=;i<=ans[now][];i++)
{
for(int j=;j<l;j++)
printf("%c",c[j+ans[now][i]]-+'a');
printf("\n");
}
}
} int main()
{
while()
{
scanf("%d",&n);
if(n==) break;
init();
get_sa(+n);
get_he();
ffind();
printf("\n");
}
return ;
} [POJ3294]
[POJ3294]
2016-07-18 11:04:28
【POJ3294】 Life Forms (后缀数组+二分)的更多相关文章
- POJ3294 Life Forms —— 后缀数组 最长公共子串
题目链接:https://vjudge.net/problem/POJ-3294 Life Forms Time Limit: 5000MS Memory Limit: 65536K Total ...
- Poj 3294 Life Forms (后缀数组 + 二分 + Hash)
题目链接: Poj 3294 Life Forms 题目描述: 有n个文本串,问在一半以上的文本串出现过的最长连续子串? 解题思路: 可以把文本串用没有出现过的不同字符连起来,然后求新文本串的heig ...
- POJ3294 Life Forms(后缀数组)
引用罗穗骞论文中的话: 将n 个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开,求后缀数组.然后二分答案,用和例3 同样的方法将后缀分成若干组,判断每组的后缀是否出现在不小于k 个的原串中 ...
- POJ3294--Life Forms 后缀数组+二分答案 大于k个字符串的最长公共子串
Life Forms Time Limit: 500 ...
- POJ 3294 Life Forms 后缀数组+二分 求至少k个字符串中包含的最长子串
Life Forms Description You may have wondered why most extraterrestrial life forms resemble humans, ...
- poj 3294 Life Forms - 后缀数组 - 二分答案
题目传送门 传送门I 传送门II 题目大意 给定$n$个串,询问所有出现在严格大于$\frac{n}{2}$个串的最长串.不存在输出'?' 用奇怪的字符把它们连接起来.然后求sa,hei,二分答案,按 ...
- BZOJ 3230: 相似子串( RMQ + 后缀数组 + 二分 )
二分查找求出k大串, 然后正反做后缀数组, RMQ求LCP, 时间复杂度O(NlogN+logN) -------------------------------------------------- ...
- BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案
BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案 Description 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l 读入单 ...
- 【bzoj4310】跳蚤 后缀数组+二分
题目描述 很久很久以前,森林里住着一群跳蚤.一天,跳蚤国王得到了一个神秘的字符串,它想进行研究. 首先,他会把串分成不超过 k 个子串,然后对于每个子串 S,他会从S的所有子串中选择字典序最大的那一个 ...
- BZOJ 1717 [USACO06DEC] Milk Patterns (后缀数组+二分)
题目大意:求可重叠的相同子串数量至少是K的子串最长长度 洛谷传送门 依然是后缀数组+二分,先用后缀数组处理出height 每次二分出一个长度x,然后去验证,在排序的后缀串集合里,有没有连续数量多于K个 ...
随机推荐
- Socket 错误一览表
出现网络联机错误Socket error #11001 表示您的计算机无法连上服务器,请检查您的Proxy设定以及Proxy相关账号,或暂时取消您防毒软件的「个人防火墙」. · 出现网络联机错误Soc ...
- 《将博客搬至CSDN》的文章
我的CSDN地址 博客园应该以后会很少来了.
- 使用graphics2D给图片上画字符
//读取图片BufferedImage frontImage = ImageIO.read(new File(eCardXMLConfigManager.geteCardXMLConfigManage ...
- [DB2]实现项目多数据库切换(上)--环境部署
基本软硬件信息:Windows 8.1 X64 / Microsoft Visual Studio 2012 / ThinkPad S3-S431 安装工具:IBM Data Studio 4.1. ...
- jquery 移除数组重复的元素----$.unique()
举例说明: var fruits=["apple","banana","pear","orange","ba ...
- MVVM模式应用 之介绍
M-V-VM (1)M:即Model,由现实世界抽象出来的模型: V:即View,视图,界面,该界面与用户输入设备进行交互: 但是View与Model如何进行交互呢? Binding便可以发挥作用了, ...
- APACHE 与IIS同时存在的情况下,给APACHE添加反向代理 共用80端口
一.首先打开IIS,将IIS的端口改成81,不要让IIS占用了80端口 二.打开APACHE的httpd.conf配置文件,将里面的端口配置成80 三.打开APACHE的虚拟目录配置文件,如:http ...
- 安装sql server 2008,提示要删除SQL Server 2005 Express 工具 怎么解决?
x86 修改注册表:HKLM\Software\Microsoft\Microsoft SQL Server\90\Tools\ShellSEM,把 ShellSEM重命名即可. x64 ...
- SQL Server2012连接SQL Server2000完美解决方案
在SQL Server2012中连接其他SQL Server数据库时可以使用以下代码: exec sp_addlinkedserver 'ITSV', '', 'SQLOLEDB', 'serveri ...
- DB2 WIN7 WIN8在指示的文件系统中找不到数据库目录
前言:win7下一些软件的不正常,跟win7的权限有很大关系. 在win7下安装db2 9.7客户端后,在cmd中运行db2cmd启动clp,输入db2的任何命令都显示:SQL ...