poj 3294 后缀数组+二分
题目大意:
给定n个字符串,求出现在不小于k个字符串中的最长子串
基本思路:
二分长度,统计个数,一般套路,就是这个跟说好的不一样啊,我非得开2倍才不re,真他妈不爽,先二分找出长度,然后根据长度输出字符串;
代码如下:
#include<cstdio>
#include<cstring>
using namespace std; typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 200000+10;
int wa[maxn],wb[maxn],wv[maxn],ws[maxn],sa[maxn],ranks[maxn],height[maxn];
char str[1010],ans[1010];
int s[maxn],loc[maxn];
bool vis[1001];
int num;
int cmp(int *r,int a,int b,int l){
return r[a]==r[b]&&r[a+l]==r[b+l];
}
void da(int *r,int n,int m){
int i,j,p,*x=wa,*y=wb,*t;
for(i=0;i<m;i++) ws[i]=0;
for(i=0;i<n;i++) ws[x[i]=r[i]]++;
for(i=1;i<m;i++) ws[i]+=ws[i-1];
for(i=n-1;i>=0;i--) sa[--ws[x[i]]]=i;
for(j=1,p=1;p<n;j*=2,m=p){
for(p=0,i=n-j;i<n;i++) y[p++]=i;
for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
for(i=0;i<n;i++) wv[i]=x[y[i]];
for(i=0;i<m;i++) ws[i]=0;
for(i=0;i<n;i++) ws[wv[i]]++;
for(i=1;i<m;i++) ws[i]+=ws[i-1];
for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i];
for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
}
}
void calHeight(int *r,int n){
int i,j,k=0;
for(i=1;i<=n;i++) ranks[sa[i]]=i;
for(i=0;i<n;i++){
if(k) k-=1;
j=sa[ranks[i]-1];
while(r[i+k]==r[j+k]) k++;
height[ranks[i]]=k;
}
}
bool check(int mid,int len){
memset(vis,false,sizeof(vis));
int cnt=0;
for(int i=2;i<=len;i++){
if(height[i]<mid){
memset(vis,false,sizeof(vis));
cnt=0;
continue;
}
if(!vis[loc[sa[i-1]]]){
vis[loc[sa[i-1]]]=true;
cnt++;
}
if(!vis[loc[sa[i]]]){
vis[loc[sa[i]]]=true;
cnt++;
}
if(cnt>num/2) return true;
}
return false;
}
void print(int mid,int len){
int cnt=0,tag=0;
memset(vis,false,sizeof(vis));
for(int i=2;i<=len;i++){
if(height[i]<mid){
memset(vis,false,sizeof(vis));
cnt=0;
tag=0;
continue;
}
if(!vis[loc[sa[i-1]]]){
vis[loc[sa[i-1]]]=true;
cnt++;
}
if(!vis[loc[sa[i]]]){
vis[loc[sa[i]]]=true;
cnt++;
}
if(cnt>num/2&&!tag){
for(int j=0;j<mid;j++){
ans[j]=s[sa[i]+j]+'a'-1;
}
ans[mid]='\0';
printf("%s\n",ans);
tag=1;
}
}
}
int main(){
while(scanf("%d",&num)==1&&num){
int cnt=0,tmp=30;
for(int i=1;i<=num;i++){
scanf("%s",str);
int len=strlen(str);
for(int j=0;j<len;j++){
loc[cnt]=i;
s[cnt++]=str[j]-'a'+1;
}
loc[cnt]=tmp;
s[cnt++]=tmp++;
}
s[cnt]=0;
da(s,cnt+1,tmp);
calHeight(s,cnt);
int left=1,right=strlen(str),mid,flag=0;
while(right>=left){
mid=(left+right)/2;
if(check(mid,cnt)){
left=mid+1;
flag=mid;
}else{
right=mid-1;
}
}
if(flag){
print(flag,cnt);
printf("\n");
}else{
printf("?\n\n");
}
}
return 0;
}
poj 3294 后缀数组+二分的更多相关文章
- POJ 3294 后缀数组
题目链接:http://poj.org/problem?id=3294 题意:给定n个字符串,求一个最长子串要求在超过一半的字符串中出现过. 如果多解按字典序输出 思路:根据<<后缀数组— ...
- POJ 2774 后缀数组 || 二分+哈希
Long Long Message Time Limit: 4000MS Memory Limit: 131072K Total Submissions: 35607 Accepted: 14 ...
- poj 3294 后缀数组 多字符串中不小于 k 个字符串中的最长子串
Life Forms Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 16223 Accepted: 4763 Descr ...
- POJ 3261 (后缀数组 二分) Milk Patterns
这道题和UVa 12206一样,求至少重复出现k次的最长字串. 首先还是二分最长字串的长度len,然后以len为边界对height数组分段,如果有一段包含超过k个后缀则符合要求. #include & ...
- POJ 1743 (后缀数组 二分) Musical Theme
看来对height数组进行分段确实是个比较常用的技巧. 题意: 一个主题是可以变调的,也就是如果这个主题所有数字加上或者减少相同的数值,可以看做是相同的主题. 一个主题在原串中至少要出现两次,而且一定 ...
- POJ 3261 后缀数组+二分
思路: 论文题- 二分+对后缀分组 这块一开始不用基数排序 会更快的(其实区别不大) //By SiriusRen #include <cstdio> #include <cstri ...
- Poj 1743 Musical Theme(后缀数组+二分答案)
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 28435 Accepted: 9604 Descri ...
- POJ 1743 [USACO5.1] Musical Theme (后缀数组+二分)
洛谷P2743传送门 题目大意:给你一个序列,求其中最长的一对相似等长子串 一对合法的相似子串被定义为: 1.任意一个子串长度都大于等于5 2.不能有重叠部分 3.其中一个子串可以在全部+/-某个值后 ...
- Poj 3261 Milk Patterns(后缀数组+二分答案)
Milk Patterns Case Time Limit: 2000MS Description Farmer John has noticed that the quality of milk g ...
随机推荐
- sqlldr - exit error code 2 in unix (merged)
http://www.orafaq.com/forum/t/146582/ Thank you for your reply. Load has been successful all the tim ...
- Opencv3.3(Linux)编译安装至python的坑
编译安装OpenCV绝对是一件让人发狂的事情,CMake繁多的选项,国内蛋疼的网速,实在让人无力吐槽,然而为了使用contrib包,我不得不重新编译他. OpenCV的编译 其实OpenCV编译并不是 ...
- 图解SSH原理_20190613
SSH仅仅是一协议标准,其具体的实现有很多,既有开源实现的OpenSSH,也有商业实现方案.使用范围最广泛的当然是开源实现OpenSSH. 2. SSH工作原理 在讨论SSH的原理和使用前,我们需要分 ...
- 21.Semaphore信号量
Semaphore是一种基于计数的信号量.它可以设定一个阈值,基于此,多个线程竞争获取许可信号,做自己的申请后归还,超过阈值后,线程申请许可信号将会被阻塞.Semaphore可以用来构建一些对象池,资 ...
- ICU lirary DownLoad
{ //https://github.com/unicode-org/icu }
- JSP自定义方法标签
1.自定义方法标签 引入方式示例: <%@ taglib prefix="fns" uri="/WEB-INF/tlds/fns.tld" %> 写 ...
- PHP发送公众号模板消息
<?php /* * 模板消息发送,电脑端测试时需要手动填写openid * 微信端会自动获取当前openid发送无需填写 */ header("Content-type: text/ ...
- 【架构】Linux的架构(architecture)
最内层是硬件,最外层是用户常用的应用,比如说firefox浏览器,evolution查看邮件,一个计算流体模型等等.硬件是物质基础,而应用提供服务.但在两者之间,还要经过一番周折. 还记得Linux启 ...
- Python--同步锁(互斥锁)、死锁(状态)、递归锁、信号量、Event对象
同步锁/互斥锁 (Lock) import time import threading def sub(): global num #在每个线程中都获取这个全局变量 #num-=1 temp=num ...
- PHP curl_multi_select函数
curl_multi_select — 等待所有cURL批处理中的活动连接 说明 int curl_multi_select ( resource $mh [, float $timeout = 1. ...