思路

后缀数组

先都拼在一起

二分+height分段

按照小于x的为分界,判断是否有一个分段中包含超过n/2个串

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct Node{
int pos,r[2];
}x[200100],midx[200100];
int n,sa[200100],ranks[200100],barrel[200100],height[200100],belong[200100],has[210],numx;
char s[200100],c[200100];
int c_sort(int n,int lim){
for(int i=0;i<2;i++){
memset(barrel,0,sizeof(barrel));
for(int j=1;j<=n;j++)
barrel[x[j].r[i]]++;
for(int j=1;j<=lim;j++)
barrel[j]+=barrel[j-1];
for(int j=n;j>=1;j--)
midx[barrel[x[j].r[i]]--]=x[j];
for(int j=1;j<=n;j++)
x[j]=midx[j];
}
ranks[x[1].pos]=1;
int cnt=1;
for(int i=2;i<=n;i++){
if(x[i].r[0]==x[i-1].r[0]&&x[i].r[1]==x[i-1].r[1])
ranks[x[i].pos]=cnt;
else
ranks[x[i].pos]=++cnt;
}
return cnt;
}
void cal_sa(int n){
for(int i=1;i<=n;i++)
x[i]=(Node){i,s[i],0};
int cnt=c_sort(n,255);
for(int i=1;cnt<n;i<<=1){
for(int j=1;j<=n;j++)
x[j]=(Node){j,(i+j<=n)?ranks[i+j]:0,ranks[j]};
cnt=c_sort(n,cnt);
}
for(int i=1;i<=n;i++)
sa[ranks[i]]=i;
for(int i=1,j=0,k;i<=n;height[ranks[i++]]=j)
for(j?j--:0,k=sa[ranks[i]-1];s[i+j]==s[j+k];j++);
}
// void init(void){
// for(int i=1;i<=n;i++)
// ST[i][0]=height[i];
// for(int i=1;i<20;i++)
// for(int j=1;j<=n;j++)
// ST[j][i]=min(ST[j][i-1],ST[min(j+(1<<(i-1)),n+10)][i-1]); // }
// int query(int l,int r){
// l=ranks[l];
// r=ranks[r];
// l++;
// if(l>r)
// swap(l,r);
// int k=0;
// while((1<<k+1)<=(r-l+1))
// k++;
// return min(ST[l][k],ST[r-(1<<k)+1][k]);
// }
bool check(int x){
// printf("check %d\n",x);
memset(has,0,sizeof(has));
int midnum=0;
has[0]=true;
if(!has[belong[sa[1]]]){
++midnum;
has[belong[sa[1]]]=true;
}
if(midnum>(numx/2)){
return true;
}
for(int i=2;i<=n;i++){
if(height[i]<x){
memset(has,0,sizeof(has));
has[0]=true;
midnum=0;
if(!has[belong[sa[i]]]){
midnum++;
has[belong[sa[i]]]=true;
}
}
else{
if(!has[belong[sa[i]]]){
midnum++;
has[belong[sa[i]]]=true;
}
}
if(midnum>(numx/2)){
return true;
}
}
return false;
}
void print(int x){
memset(has,0,sizeof(has));
int midnum=0,f=1;
has[0]=true;
if(!has[belong[sa[1]]]){
++midnum;
has[belong[sa[1]]]=true;
}
if(midnum>(numx/2)&&f){
f=0;
for(int j=1;j<=x;j++)
putchar(s[sa[1]+j-1]);
putchar('\n');
}
for(int i=2;i<=n;i++){
if(height[i]<x){
f=1;
memset(has,0,sizeof(has));
has[0]=true;
midnum=0;
if(!has[belong[sa[i]]]){
midnum++;
has[belong[sa[i]]]=true;
}
}
else{
if(!has[belong[sa[i]]]){
midnum++;
has[belong[sa[i]]]=true;
}
}
if(midnum>(numx/2)&&f){
f=0;
for(int j=1;j<=x;j++)
putchar(s[sa[i]+j-1]);
putchar('\n');
}
}
}
void init(void){
memset(s,0,sizeof(s));
memset(height,0,sizeof(height));
memset(sa,0,sizeof(sa));
memset(ranks,0,sizeof(ranks));
memset(belong,0,sizeof(belong));
memset(midx,0,sizeof(midx));
memset(x,0,sizeof(x));
}
int main(){
// freopen("test.in","r",stdin);
// freopen("test.out","w",stdout);
int cnt=0;
while(scanf("%d",&numx)==1&&numx){
init();
n=0;
cnt++;
if(cnt>1)
putchar('\n');
if(numx==1){
scanf("%s",s);
printf("%s\n",s);
continue;
}
for(int i=1;i<=numx;i++){
scanf("%s",c+1);
int len=strlen(c+1);
for(int j=1;j<=len;j++){
s[n+j]=c[j];
belong[n+j]=i;
}
n+=len;
s[++n]='z'+i;
belong[n]=0;
}
// for(int i=1;i<=n;i++)
// putchar(s[i]);
// putchar('\n');
cal_sa(n);
// for(int i=1;i<=n;i++){
// printf("%d ",height[i]);
// }
// printf("\n");
// for(int i=1;i<=n;i++){
// printf("%d ",belong[sa[i]]);
// }
// printf("\n");
// printf("ok\n");
int l=0,r=n,ans=0;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid))
l=mid+1,ans=mid;
else
r=mid-1;
}
// printf("ans=%d\n",ans);
if(ans==0){
printf("?\n");
}
else{
print(ans);
}
}
return 0;
}

UVA11107 Life Forms的更多相关文章

  1. UVA11107 Life Forms --- 后缀数组

    UVA11107 Life Forms 题目描述: 求出出现在一半以上的字符串内的最长字符串. 数据范围: \(\sum len(string) <= 10^{5}\) 非常坑的题目. 思路非常 ...

  2. UVA11107 Life Forms SA模板

    Life Forms Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 16827   Accepted: 4943 Descr ...

  3. UVA-11107 Life Forms(后缀数组)

    题目大意:给出n个字符串,找出所有最长的在超过一半的字符串中出现的子串. 题目分析:将所有的字符串连成一个,二分枚举长度,每次用O(n)的时间复杂度判断.连接字符串的时候中间添一个没有出现过的字符. ...

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

    题解: 题意: 输入n个DNA序列,你的任务是求出一个长度最大的字符串,使得它在超过一半的DNA序列中出现.如果有多解,按照字典序从小到大输入所有解. 把n个DNA序列拼在一起,中间用没有出现过的字符 ...

  5. 【UVA11107 训练指南】Life Forms【后缀数组】

    题意 输入n(n<=100)个字符串,每个字符串长度<=1000,你的任务是找出一个最长的字符串使得超过一半的字符串都包含这个字符串. 分析 训练指南上后缀数组的一道例题,据说很经典(估计 ...

  6. Wizard Framework:一个自己开发的基于Windows Forms的向导开发框架

    最近因项目需要,我自己设计开发了一个基于Windows Forms的向导开发框架,目前我已经将其开源,并发布了一个NuGet安装包.比较囧的一件事是,当我发布了NuGet安装包以后,发现原来已经有一个 ...

  7. xamarin.forms新建项目android编译错误

    vs2015 update3 新建的xamarin.forms项目中的android项目编译错误.提示缺少android_m2repository_r22.zip,96659D653BDE0FAEDB ...

  8. ASP.NET Forms 身份验证

    ASP.NET Forms 身份验证 在开发过程中,我们需要做的事情包括: 1. 在 web.config 中设置 Forms 身份验证相关参数.2. 创建登录页. 登录页中的操作包括: 1. 验证用 ...

  9. Xamarin.Forms 简介

    An Introduction to Xamarin.Forms 来源:http://developer.xamarin.com/guides/cross-platform/xamarin-forms ...

随机推荐

  1. 2018-2019-2 20165336《网络对抗技术》Exp0 Kali安装 Week1

    2018-2019-2 20165336<网络对抗技术>Exp0 Kali安装 Week1 一.选择官网kali linux系统的版本 二.配置虚拟机 根据 安装教程(https://bl ...

  2. python 去掉重复元素 学到再添加

    1. python 内置函数 set(可迭代对象) 返回无重复元素的集合.如在分类中,classification为类别数组 set(classification)为类别数 2.numpy np.un ...

  3. python一次性解压多层嵌套zip压缩包

    zip包里的结构不是固定的,有可能只需要解压一次就完成了,有可能解压后里面还存在zip文件,需要继续进行解压缩 写了个简单的递归函数来实现解压非固定结构zip包,若解压后的zip子目录下仍含有zip文 ...

  4. 构造方法,this关键字,static关键字,封装,静态变量

    1.构造方法 构造方法是一种特殊的方法,是专门用于创建/实例化对象的方法. 构造方法根据是否有参数分为两类:1.无参构造方法  2.有参构造方法 1.1无参构造方法 无参构造方法就是构造方法中没有参数 ...

  5. C# Unity依赖注入

    简介: 控制反转:我们向IOC容器发出获取一个对象实例的一个请求,IOC容器便把这个对象实例“注入”到我们的手中,在这个过程中你不是一个控制者而是一个请求者,依赖于容器提供给你的资源,控制权落到了容器 ...

  6. 第一次安装myeclipse+tomcat经验

    在网上找了很多资料,这里记录一下验证有用的资料,避免以后走弯路 1.安装myeclipse 参考如下URL,亲测有用 https://blog.csdn.net/qingjianduoyun/arti ...

  7. mvc jquery ajax传递数组null问题

    mvc jquery ajax传递数,  areaIds是个int数组.后台action用list<int>接收.当我想传空值时,先用null传递,结果action收到的AreaIds竟然 ...

  8. bochs模拟器创建映像文件 、写入文件并启动

    安装 bochs,dd for windows,nasm,并将安装目录加入到环境变量中. 我用的bochs版本是2.6.8 1.用 bochs 中 bximage.exe 创建新的 img 文件 2. ...

  9. php 中 global 与 $GLOBAL 的区别

    很多人都认为global和$GLOBALS[]只是写法上面的差别,其实不然. 根据官方的解释是$GLOBALS['var'] 是外部的全局变量$var本身. global $var 是外部$var的同 ...

  10. 转载 usb_alloc_coherent 和 usb_free_coherent

    今天做移植的时候,随手记录一下,今天所遇到的问题解决方法. 在linux2.6.34和之前的代码中还可以使用usb_buffer_alloc 和 usb_buffer_free 这两个函数,在2.6. ...