poj 3294
| Time Limit: 5000MS | Memory Limit: 65536K | |
| Total Submissions: 12688 | Accepted: 3552 |
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 ? 二分长度把height分组,同组在不同的n/2个串里就是答案,只需记录该组中任意一个后缀的起点
SA尤其要注意开够数组,免得连接串的时候出错
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MN 200003
using namespace std; int n,m,nm,nnm;
char s1[MN];
int s[MN],a[MN];
int v[MN],sa[MN],q[MN],rank[MN],h[MN],mmh=,len,nu[MN],st[MN];
bool w[];
inline void gr(int x){
rank[sa[]]=;
for (int i=;i<=n;i++) rank[sa[i]]=(s[sa[i]]==s[sa[i-]]&&s[sa[i]+x]==s[sa[i-]+x])?rank[sa[i-]]:rank[sa[i-]]+;
for (int i=;i<=n;i++) s[i]=rank[i];
}
inline void gv(){memset(v,,sizeof(v));for (int i=;i<=n;i++) v[s[i]]++;for (int i=;i<=2e5;i++)v[i]+=v[i-];}
inline void gsa(){
gv();for (int i=n;i>=;i--) sa[v[s[i]]--]=i;gr();
for (int i=;i<n;i<<=){
gv();for (int j=n;j>=;j--) if (sa[j]>i) q[v[s[sa[j]-i]]--]=sa[j]-i;
for (int j=n-i+;j<=n;j++) q[v[s[j]]--]=j;
for (int j=;j<=n;j++) sa[j]=q[j];gr(i);
if (rank[sa[n]]==n) return;
}
}
inline void gh(){for (int i=,k=,j;i<=n;h[rank[i++]]=k) for (k?k--:,j=sa[rank[i]-];a[i+k]==a[j+k]&&i+k<=n&&j+k<=n;k++);}
int main(){
scanf("%d",&n);
while(n){
nm=;
for (int i=;i<=n;i++){
scanf("%s",s1);
m=strlen(s1);
for (int j=;j<m;j++) a[++nm]=s1[j]-'a',nu[nm]=i;a[++nm]=+i;
}
nnm=n;
n=nm;
for (int i=;i<=nm;i++) s[i]=a[i];
gsa();gh();
int l=,r=n,mid,bo=,i,j,k,mmh,pos;
while(l<r){
mid=(l+r+)>>;
for (i=,j,k=;i<=n;i=k++){
memset(w,,sizeof(w));mmh=;
while (h[k]>=mid&&k<=n) k++;
for (j=i;j<k;j++) if (!w[nu[sa[j]]]&&nu[sa[j]]) mmh++,w[nu[sa[j]]]=;
if (mmh*>nnm) break;
}
if (i<=n) l=mid;else r=mid-;
}
pos=;
for (i=,j,k=;i<=n;i=k++){
memset(w,,sizeof(w));mmh=;
while (h[k]>=l&&k<=n) k++;
for (j=i;j<k;j++) if (!w[nu[sa[j]]]&&nu[sa[j]]) mmh++,w[nu[sa[j]]]=;
if (mmh*>nnm) st[++pos]=sa[i];
}
if (l==) printf("?\n");else
for (int i=;i<=pos;putchar('\n'),i++)
for (int j=;j<l;j++) putchar(a[st[i]+j]+'a');
putchar('\n');
scanf("%d",&n);
}
}
3952K 750MS G++ 2114B
poj 3294的更多相关文章
- POJ 3294 n个串中至少一半的串共享的最长公共子串
Life Forms Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 12484 Accepted: 3502 Descr ...
- Poj 3294 Life Forms (后缀数组 + 二分 + Hash)
题目链接: Poj 3294 Life Forms 题目描述: 有n个文本串,问在一半以上的文本串出现过的最长连续子串? 解题思路: 可以把文本串用没有出现过的不同字符连起来,然后求新文本串的heig ...
- POJ - 3294~Relevant Phrases of Annihilation SPOJ - PHRASES~Substrings POJ - 1226~POJ - 3450 ~ POJ - 3080 (后缀数组求解多个串的公共字串问题)
多个字符串的相关问题 这类问题的一个常用做法是,先将所有的字符串连接起来, 然后求后缀数组 和 height 数组,再利用 height 数组进行求解. 这中间可能需要二分答案. POJ - 3294 ...
- POJ 3294 后缀数组
题目链接:http://poj.org/problem?id=3294 题意:给定n个字符串,求一个最长子串要求在超过一半的字符串中出现过. 如果多解按字典序输出 思路:根据<<后缀数组— ...
- POJ 3294 Life Forms(后缀数组+二分答案)
[题目链接] http://poj.org/problem?id=3294 [题目大意] 求出在至少在一半字符串中出现的最长子串. 如果有多个符合的答案,请按照字典序输出. [题解] 将所有的字符串通 ...
- poj 3294 Life Forms - 后缀数组 - 二分答案
题目传送门 传送门I 传送门II 题目大意 给定$n$个串,询问所有出现在严格大于$\frac{n}{2}$个串的最长串.不存在输出'?' 用奇怪的字符把它们连接起来.然后求sa,hei,二分答案,按 ...
- POJ 3294 Life Forms [最长公共子串加强版 后缀数组 && 二分]
题目:http://poj.org/problem?id=3294 Life Forms Time Limit: 5000MS Memory Limit: 65536K Total Submiss ...
- POJ 3294 出现在至少K个字符串中的子串
在掌握POJ 2774(两个串求最长公共子串)以及对Height数组分组后,本题还是容易想出思路的. 首先用字符集外的不同字符连接所有串,这是为了防止两个后缀在比较时超过某个字符串的分界.二分子串的长 ...
- POJ 3294 Life Forms 后缀数组+二分 求至少k个字符串中包含的最长子串
Life Forms Description You may have wondered why most extraterrestrial life forms resemble humans, ...
- POJ 3294 二分找超过一半字符串中存在的子串
题目大意: 给定n个字符串,求出现在不小于k/2个字符串中的最长子串. 二分找对应子串长度的答案,将所有字符串链接成一个长字符串求后缀数组,记录每一个位置本属于第几个字符串,利用height查询的时候 ...
随机推荐
- CentOS 7部署ASP.NET Core应用程序
看了几篇大牛写的关于Linux部署ASP.NET Core程序的文章,今天来实战演练一下.2017年最后一个工作日,提前预祝大家伙元旦快乐.不扯淡,直接进入正题.您有任何问题请在评论区留言. 1.环境 ...
- iOS 视频开发学习
原文:浅谈iOS视频开发 这段时间对视频开发进行了一些了解,在这里和大家分享一下我自己觉得学习步骤和资料,希望对那些对视频感兴趣的朋友有些帮助. 一.iOS系统自带播放器 要了解iOS视频开发,首先我 ...
- 724. Find Pivot Index
Given an array of integers nums, write a method that returns the "pivot" index of this arr ...
- Java 管程解决生产者消费者问题
同样是实验存档.//.. 依然以生产者消费者问题作为背景. 管程(=“资源管理程序”)将资源和对资源的操作封装起来,资源使用者通过接口操作资源就 ok,不用去考虑进程同步的问题. 管程: packag ...
- BZOJ 4818 SDOI2017 序列计数
刚出炉的省选题,还是山东的. 自古山东出数学和网络流,堪称思维的殿堂,比某地数据结构成风好多了. 废话不说上题解. 1.题面 求:n个数(顺序可更改),值域为[1,m],和为p的倍数,且这些数里面有质 ...
- 什么是AJAX? AJAX:”Asynchronous JavaScript and XML”中文意思:异步JavaScript和XML。
指一种创建交互式网页应用的网页开发技术. AJAX并非缩写词,而是由Jesse James Gaiiett创造的名词. 不是指一种单一的技术,而是有机地利用了一系列相关的技术: web标准( Stan ...
- Java 浅析Thread.join()
概要 本文分为三部分对 Thread.join() 进行分析: 1. join() 的示例和作用 2. join() 源码分析 3. 对网上其他分析 join() 的文章提出疑问 1. join() ...
- 手撕vue-cli配置文件——config篇
最近一直在研究webpack,突然想看看vue-cli中的webpack是如何配置,查阅了很多相关的文章,所以也想出几篇关于vue-cli配置的东西.正所谓"工欲善其事必先利其器" ...
- Java自己动手写连接池一
自己动手写连接池,废话不多说,直接上代码,读取配置文件 package com.kama.cn; import java.io.IOException;import java.io.InputStre ...
- linux mysql添加、删除用户、用户权限及mysql最大字段数量
1. 登录: mysql -u username -p 显示全部的数据库: show databases; 使用某一个数据库: use databasename; 显示一个数据库的全部表: show ...