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查询的时候 ...
随机推荐
- JavaScript基础1——基本概念
关于JS的概念 JavaScript 是一种弱类型语言. JavaScript 是一种客户端脚本语言(脚本语言是一种轻量级的编程语言). JavaScript是基于对象的.(因为面向对象需要具有封装. ...
- jsDOM编程-乌龟抓小鸡游戏
<html> <head> <title>js乌龟抓小鸡游戏 </title> <meta http-equiv="conten ...
- 数据库SQL优化
1.对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...
- 如何写一个SSH项目(三)如何进行交互的
下面以登录为例子,展示从前台到后端的一整套流程并进行分析. 首先介绍一下我的SSH的分层结构 action和service一起是业务逻辑层 action层调用service层 dao ...
- 通过js添加的元素点击事件无法触发
var blk_have ='<div class="sw-off"></div>'; $('#blk').prepend(blk_have); $(doc ...
- idea为tomcat设置虚拟地址
1.设置tomcat的server.xml <Host name="localhost" appBase="webapps" unpackWARs=&qu ...
- .Net WinForm 控件键盘消息处理剖析
在WinForm控件上我们可以看到很多关于键盘消息处理的方法,比如OnKeyDown, OnKeyPress, ProcessCmdKey, ProcessDialogKey,IsInputKey等等 ...
- Java笔记:Java 流(Stream)、文件(File)和IO
更新时间:2018-1-7 12:27:21 更多请查看在线文集:http://android.52fhy.com/java/index.html java.io 包几乎包含了所有操作输入.输出需要的 ...
- linux网路编程:字节序(大端、小端、网络、主机)
字节序:就是数据在内存中的存放顺序,也可称之为端模式. 大端模式和小端模式的定义 1) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端. 2) Big-End ...
- 可视化编程开发板TurnipBit支持LED亮度可调功能
微软的makecode编辑器更新至版本v0.12.64.新增LED的可调亮度功能.而作为中文版可视化编程的口袋计算机TurnipBit完全兼容micro:bit,同样支持LED的亮度可调功能. 该项功 ...