UVA-11107 Life Forms(求出现K次的子串,后缀数组+二分答案)

题解:
题意:
输入n个DNA序列,你的任务是求出一个长度最大的字符串,使得它在超过一半的DNA序列中出现。如果有多解,按照字典序从小到大输入所有解。
把n个DNA序列拼在一起,中间用没有出现过的字符分割。然后求出height数组。
二分满足要求的字符串长度L,然后判断是否可行。
判断可行:
分组方法,如果某一组(段)有超过n/2的DNA串(是对应的输入的DNA串要有n/2个),则可行。
参考代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=*+;
const int maxm=*;
int idx[maxm],n;
struct SuffixArray{
int s[maxm];
int sa[maxm],height[maxm],rank[maxm],n;
int t[maxm*],t2[maxm*];
long long cnt[maxm];
void clear(){n=;}
void build_sa(int m)
{
int i,*x=t,*y=t2;
for(i=;i<m;i++) cnt[i]=;
for(i=;i<n;i++) cnt[x[i]=s[i]]++;
for(i=;i<m;i++) cnt[i]+=cnt[i-];
for(i=n-;i>=;i--) sa[--cnt[x[i]]]=i;
for(int k=,p=;k<n;k <<=)
{
p=;
for(i=n-k;i<n;i++) y[p++]=i;
for(i=;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
for(i=;i<m;i++) cnt[i]=;
for(i=;i<n;i++) cnt[x[y[i]]]++;
for(i=;i<m;i++) cnt[i]+=cnt[i-];
for(i=n-;i>=;i--) sa[--cnt[x[y[i]]]]=y[i];
swap(x,y);
p=;x[sa[]]=;
for(i=;i<n;i++)
{
if(y[sa[i-]]==y[sa[i]]&&y[sa[i-]+k]==y[sa[i]+k]) x[sa[i]]=p-;
else x[sa[i]]=p++;
}
if(p>=n) break;
m=p;
}
}
void build_height()
{
int k=;
for(int i=;i<n;i++) rank[sa[i]]=i;
for(int i=;i<n;i++)
{
if(k) k--;
if(!rank[i]) continue;
int j=sa[rank[i]-];
while(s[i+k]==s[j+k]) k++;
height[rank[i]]=k;
}
}
} SA; inline void add(int ch,int id)
{
idx[SA.n]=id;
SA.s[SA.n++]=ch;////
} int flag[maxn];
inline int check(int ans)
{
int check_clock=;
memset(flag,,sizeof(flag));
for(int i=;i<SA.n;i++)
{
if(SA.height[i]>=ans)
{
flag[idx[SA.sa[i]]]=check_clock;
flag[idx[SA.sa[i-]]]=check_clock;
}
else
{
int cnt=;
for(int j=;j<n;j++) if(flag[j]==check_clock) cnt++;
if(cnt>n/) return true;
flag[idx[SA.sa[i]]]=++check_clock;
}
}
return false;
} inline void print_ans(int l,int r)
{
for(int i=l;i<=r;i++) printf("%c",SA.s[i]+'a'-);
printf("\n");
} inline void print(int ans)
{
int check_clock=;
memset(flag,,sizeof(flag));
for(int i=;i<SA.n;i++)
{
if(SA.height[i]>=ans)
{
flag[idx[SA.sa[i]]]=check_clock;
flag[idx[SA.sa[i-]]]=check_clock;
}
else
{
int cnt=;
for(int j=;j<n;j++) if(flag[j]==check_clock) cnt++;
if(cnt>n/) print_ans(SA.sa[i-],SA.sa[i-]+ans-);
flag[idx[SA.sa[i]]]=++check_clock;
}
}
}
char s[+];
int kase=;
int main()
{
int maxlen;
while(scanf("%d",&n)==&&n)
{
if(kase++) printf("\n");
SA.clear();
maxlen=;
for(int i=;i<n;i++)
{
scanf("%s",s);
int l=strlen(s);
maxlen=max(maxlen,l);
for(int j=;j<l;j++) add(s[j]-'a'+,i);
add(+i,n);
}
if(n==) {printf("%s\n",s);continue;}
SA.build_sa(+n);
SA.build_height();
int l=,r=maxlen,ans=;
while(l<=r)
{
int mid=((l+r)>>);
if(check(mid)) ans=mid,l=mid+;
else r=mid-;
}
if(ans) print(ans);
else printf("?\n");
}
return ;
}
UVA-11107 Life Forms(求出现K次的子串,后缀数组+二分答案)的更多相关文章
- POJ3294--Life Forms 后缀数组+二分答案 大于k个字符串的最长公共子串
Life Forms Time Limit: 500 ...
- POJ 3294 Life Forms(后缀数组+二分答案)
[题目链接] http://poj.org/problem?id=3294 [题目大意] 求出在至少在一半字符串中出现的最长子串. 如果有多个符合的答案,请按照字典序输出. [题解] 将所有的字符串通 ...
- poj 3294 Life Forms - 后缀数组 - 二分答案
题目传送门 传送门I 传送门II 题目大意 给定$n$个串,询问所有出现在严格大于$\frac{n}{2}$个串的最长串.不存在输出'?' 用奇怪的字符把它们连接起来.然后求sa,hei,二分答案,按 ...
- ural1297 求最长回文子串 | 后缀数组
#include<cstdio> #include<algorithm> #include<cstring> #define N 20005 using names ...
- POJ 3294 Life Forms 后缀数组+二分 求至少k个字符串中包含的最长子串
Life Forms Description You may have wondered why most extraterrestrial life forms resemble humans, ...
- uva 11107 Life Forms
题意:给你N个串,求一个串在大于等于N/2的模板串中连续出现.如果有多解按字典序最小输出. 白书模板题.二分答案+合并模板串成一个新串,扫秒新串的height数组. 考查后缀数组+LCP #inclu ...
- POJ 3294 UVA 11107 Life Forms 后缀数组
相同的题目,输出格式有区别. 给定n个字符串,求最长的子串,使得它同时出现在一半以上的串中. 不熟悉后缀数组的童鞋建议先去看一看如何用后缀数组计算两个字符串的最长公共子串 Ural1517 这道题的思 ...
- UVA - 11107 Life Forms (广义后缀自动机+后缀树/后缀数组+尺取)
题意:给你n个字符串,求出在超过一半的字符串中出现的所有子串中最长的子串,按字典序输出. 这道题算是我的一个黑历史了吧,以前我的做法是对这n个字符串建广义后缀自动机,然后在自动机上dfs,交上去AC了 ...
- UVA 11107 Life Forms——(多字符串的最长公共子序列,后缀数组+LCP)
题意: 输入n个序列,求出一个最大长度的字符串,使得它在超过一半的DNA序列中连续出现.如果有多解,按照字典序从小到大输出所有解. 分析:这道题的关键是将多个字符串连接成一个串,方法是用不同的分隔符把 ...
随机推荐
- 去重算法,简单粗暴&优化版
Remove Repeat 一.去重原理 1.进行排序 2.判断是否满足 '两个字符串相同' 的条件,相同则累加重复次数,并使用continue继续下一次循环 3.当条件不满足时,将该字符串和累计数加 ...
- Spring注解之@RestControllerAdvice
前言 前段时间部门搭建新系统,需要出异常后统一接口的返回格式,于是用到了Spring的注解@RestControllerAdvice.现在把此注解的用法总结一下. 用法 首先定义返回对象Respons ...
- Hybrid App: 看看第三方WebViewJavascriptBridge是如何来实现Native和JavaScript交互
一.简介 在前面两篇文章中已经介绍了Native与JavaScript交互的几种方式,依次是JavaScriptCore框架.UI组件UIWebView.WebKit框架,这几种方式都是苹果公司提供的 ...
- RocketMQ消息轨迹-设计篇
目录 1.消息轨迹数据格式 2.记录消息轨迹 3.如何存储消息轨迹数据 @(本节目录) RocketMQ消息轨迹主要包含两篇文章:设计篇与源码分析篇,本节将详细介绍RocketMQ消息轨迹-设计相关. ...
- 微信中使用popup等弹窗组件时点击输入框input键盘弹起导致IOS中按钮无效处理办法
因为在IOS微信中在弹窗中使用input使键盘弹起,使弹窗的位置上移,当键盘关闭时页面还在上面,弹窗位移量也在上面,只有下拉才能回到原位,这样弹窗也消失了.我的处理办法就是在键盘弹起和消失的时候,让页 ...
- 【Luogu 1993】差分约束系统问题——小K的农场
Luogu P1993 前置知识:最短路径相关算法 如果一个系统由n个变量和m个约束条件组成,形成m个形如ai-aj≤k的不等式(i,j∈[1,n],k为常数),则称其为差分约束系统. 显然题目中给出 ...
- 全网最通俗易懂的Kafka入门!
前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 在这篇之前已经写过两篇基础文章了,强烈建议先去阅读: ...
- 前端vue如何下载或者导出word文件和excel文件
前端用vue怎么接收并导出文件 window.location.href = "excel地址" 如果是 get 请求,那直接换成 window.open(url) 就行了 创建一 ...
- django-formset实现数据表的批量操作
什么是formset 我们知道forms组件是用来做表单验证,更准确一点说,forms组件是用来做数据库表中一行记录的验证.有forms组件不同,formset是同科同时验证表中的多行记录,即form ...
- 痞子衡嵌入式:恩智浦i.MX RTxxx系列MCU启动那些事(4)- OTP及其烧写方法
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RTxxx系列MCU的OTP. 在i.MXRTxxx启动系列第二篇文章 Boot配置(ISP Pin, OTP) 里痞子 ...