给n个字符串,求最长的多于n/2个字符串的公共子串。

依然是二分判定+height分组。

  • 把这n个字符串连接,中间用不同字符隔开,跑后缀数组计算出height;
  • 二分要求的子串长度,判断是否满足:height分组,统计一个组不同的字符串个数是否大于n/2;
  • 最后输出方案,根据二分得出的子串长度的结果,直接再遍历一遍height,因为这儿是有序的后缀所以找到一个就直接输出。
 #include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define MAXN 111000 int wa[MAXN],wb[MAXN],wv[MAXN],ws[MAXN];
int cmp(int *r,int a,int b,int l){
return r[a]==r[b] && r[a+l]==r[b+l];
}
int sa[MAXN],rank[MAXN],height[MAXN];
void SA(int *r,int n,int m){
int *x=wa,*y=wb; for(int i=; i<m; ++i) ws[i]=;
for(int i=; i<n; ++i) ++ws[x[i]=r[i]];
for(int i=; i<m; ++i) ws[i]+=ws[i-];
for(int i=n-; i>=; --i) sa[--ws[x[i]]]=i; int p=;
for(int j=; p<n; j<<=,m=p){
p=;
for(int i=n-j; i<n; ++i) y[p++]=i;
for(int i=; i<n; ++i) if(sa[i]>=j) y[p++]=sa[i]-j;
for(int i=; i<n; ++i) wv[i]=x[y[i]];
for(int i=; i<m; ++i) ws[i]=;
for(int i=; i<n; ++i) ++ws[wv[i]];
for(int i=; i<m; ++i) ws[i]+=ws[i-];
for(int i=n-; i>=; --i) sa[--ws[wv[i]]]=y[i];
swap(x,y); x[sa[]]=; p=;
for(int i=; i<n; ++i) x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p-:p++;
} for(int i=; i<n; ++i) rank[sa[i]]=i;
int k=;
for(int i=; i<n-; height[rank[i++]]=k){
if(k) --k;
for(int j=sa[rank[i]-]; r[i+k]==r[j+k]; ++k);
}
} int n,m,r[MAXN],belong[MAXN];
bool isok(int len){
int cnt=;
bool vis[]={};
for(int i=; i<=n; ++i){
if(height[i]>=len){
if(!vis[belong[sa[i]]]){
vis[belong[sa[i]]]=;
++cnt;
}
if(!vis[belong[sa[i-]]]){
vis[belong[sa[i-]]]=;
++cnt;
}
}else{
if(cnt>(m>>)) return ;
memset(vis,,sizeof(vis));
cnt=;
}
}
return ;
}
void pnt(int len){
int cnt=,idx;
bool vis[]={};
for(int i=; i<=n; ++i){
if(height[i]>=len){
idx=sa[i];
if(!vis[belong[sa[i]]]){
vis[belong[sa[i]]]=;
++cnt;
}
if(!vis[belong[sa[i-]]]){
vis[belong[sa[i-]]]=;
++cnt;
}
}else{
if(cnt>(m>>)){
for(int j=; j<len; ++j){
putchar(r[idx+j]+'a'-);
}
putchar('\n');
}
memset(vis,,sizeof(vis));
cnt=;
}
}
}
int main(){
char s[];
while(~scanf("%d",&m) && m){
n=;
for(int i=; i<m; ++i){
scanf("%s",s);
for(int j=; s[j]; ++j){
belong[n]=i;
r[n++]=s[j]-'a'+;
}
r[n++]=+i;
}
r[--n]=;
SA(r,n+,);
int l=,r=;
while(l<r){
int mid=l+r+>>;
if(isok(mid)) l=mid;
else r=mid-;
}
if(l==) puts("?");
else pnt(l);
putchar('\n');
}
return ;
}

POJ3294 Life Forms(二分+后缀数组)的更多相关文章

  1. 2018.11.28 poj3294 Life Forms(后缀数组+双指针)

    传送门 后缀数组经典题目. 我们先把所有的字符串都接在一起. 然后求出hththt数组和sasasa数组. 然后对于sasasa数组跑双指针统计答案. 如果双指针包括进去的属于不同字符串的数量达到了题 ...

  2. poj3294 Life Forms(后缀数组)

    [题目链接] http://poj.org/problem?id=3294 [题意] 多个字符串求出现超过R次的最长公共子串. [思路] 二分+划分height,判定一个组中是否包含不小于R个不同字符 ...

  3. POJ3294 Life Forms 【后缀数组】

    生命形式 时间限制: 5000MS   内存限制: 65536K 提交总数: 16660   接受: 4910 描述 你可能想知道为什么大多数外星人的生命形式与人类相似,不同的是表面特征,如身高,肤色 ...

  4. BZOJ 2946 [Poi2000]公共串 (二分+Hash/二分+后缀数组/后缀自动机)

    求多串的最长公共字串. 法1: 二分长度+hash 传送门 法2: 二分+后缀数组 传送门 法3: 后缀自动机 拿第一个串建自动机,然后用其他串在上面匹配.每次求出SAM上每个节点的最长匹配长度后,再 ...

  5. POJ 3294 Life Forms(后缀数组+二分答案)

    [题目链接] http://poj.org/problem?id=3294 [题目大意] 求出在至少在一半字符串中出现的最长子串. 如果有多个符合的答案,请按照字典序输出. [题解] 将所有的字符串通 ...

  6. HDU4080 Stammering Aliens(二分 + 后缀数组)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4080 Description Dr. Ellie Arroway has establish ...

  7. HDU5853 Jong Hyok and String(二分 + 后缀数组)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5853 Description Jong Hyok loves strings. One da ...

  8. 【HDU 5030】Rabbit's String (二分+后缀数组)

    Rabbit's String Problem Description Long long ago, there lived a lot of rabbits in the forest. One d ...

  9. POJ-3294-Life Forms(后缀数组-不小于 k 个字符串中的最长子串)

    题意: 给定 n 个字符串,求出现在不小于 k 个字符串中的最长子串. 分析: 将 n 个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开,求后缀数组. 然后二分答案,将后缀分成若干组,判断 ...

随机推荐

  1. pdb在python程序中应用

    1.什么是pdb? pdb是python提供的调试程序的一种工具. 2.为什么需要pdb模块? 当我们的程序越写越大的时候,我们用print xxx 这种方式打断点,调试,非常不方便,这个时候我们需要 ...

  2. Where can I find the IPA logs

    Retrieving the IPA logs will differ depending on which base image was used. Operating system that do ...

  3. 聊聊、Java SPI

    SPI,Service Provider Interface,服务提供者接口. Animal 接口 package com.rockcode.www.spi; public interface Ani ...

  4. 3D U-Net卷积神经网络

    3D U-Net这篇论文的诞生主要是为了处理一些块状图(volumetric images),基本的原理跟U-Net其实并无大差,因为3D U-Net就是用3D卷积操作替换了2D的,不过在这篇博文中我 ...

  5. VMware下Linux配置局域网和外网访问

    我想尝试的是利用本机的ip+port来访问虚拟机上的web服务器,因为这样的话,我就能够将我的web服务器部署成为一个能让外网访问的服务器了,首先说下我的环境: 主机:系统win7,ip地址172.1 ...

  6. [常识]Windows系统里休眠和睡眠的区别?

    睡眠和休眠都是笔记本电脑的节能方式,但有细微的差别: 睡眠还保持着开机状态的,休眠是关机了,但是再次开机之后和关闭时的系统状态是一样的. 睡眠还是保持着系统运行数据在内存中,而休眠则将内存中的数据保存 ...

  7. Android5.0新特性

    1.Activity转场动画 首先,把之前启动Activity的代码改成下面的写法: (如果低版本需要加注解@RequiresApi(api = Build.VERSION_CODES.LOLLIPO ...

  8. Android记事本06

    昨天: activity的生命周期 今天: activity横竖屏切换的生命周期 遇到的问题: 为了匹配ADK,下载了更旧的版本SDK,布局文件仍然无法显示.

  9. http和Tcp的长连接和短连接

    . http协议和tcp/ip 协议的关系(1) http是应用层协议,tcp协议是传输层协议,ip协议是网络协议.(2) IP协议主要解决网络路由和寻址问题(3) tcp协议主要解决在IP层协议之上 ...

  10. 用canvas实现鼠标拖动绘制矩形框

    需要用到jCanvas插件和jQuery. jCanvas下载:https://raw.githubusercontent.com/caleb531/jcanvas/master/jcanvas.mi ...