【题目链接】 http://poj.org/problem?id=3080

【题目大意】

  求k个串的最长公共子串,如果存在多个则输出字典序最小,如果长度小于3则判断查找失败。

【题解】

  将所有字符串通过拼接符拼成一个串,做一遍后缀数组,二分答案,对于二分所得值,将h数组大于这个值的相邻元素分为一组,判断组内元素是否覆盖全字典,是则答案成立,对于答案扫描sa,输出第一个扫描到的子串即可。

【代码】

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int N=2000010;
int n,m,rank[N],sa[N],h[N],tmp[N],cnt[N],ans,a[N],s[N]; char str[N];
void suffixarray(int n,int m){
int i,j,k;n++;
for(i=0;i<2*n+5;i++)rank[i]=sa[i]=h[i]=tmp[i]=0;
for(i=0;i<m;i++)cnt[i]=0;
for(i=0;i<n;i++)cnt[rank[i]=s[i]]++;
for(i=1;i<m;i++)cnt[i]+=cnt[i-1];
for(i=0;i<n;i++)sa[--cnt[rank[i]]]=i;
for(k=1;k<=n;k<<=1){
for(i=0;i<n;i++){
j=sa[i]-k;
if(j<0)j+=n;
tmp[cnt[rank[j]]++]=j;
}sa[tmp[cnt[0]=0]]=j=0;
for(i=1;i<n;i++){
if(rank[tmp[i]]!=rank[tmp[i-1]]||rank[tmp[i]+k]!=rank[tmp[i-1]+k])cnt[++j]=i;
sa[tmp[i]]=j;
}memcpy(rank,sa,n*sizeof(int));
memcpy(sa,tmp,n*sizeof(int));
if(j>=n-1)break;
}for(j=rank[h[i=k=0]=0];i<n-1;i++,k++)
while(~k&&s[i]!=s[sa[j-1]+k])h[j]=k--,j=rank[sa[j]+1];
}int len[N],u,K;
vector<int> S[N];
bool vis[4010];
bool check(int L){
int cur=-1;
for(int i=1;i<=u;i++){
if(h[i]<L)S[++cur].clear();
S[cur].push_back(i);
}
for(int i=0;i<=cur;i++){
if(S[i].size()>=n){
memset(vis,0,sizeof(vis));
for(int j=0;j<S[i].size();j++){
int k=S[i][j];
int x=upper_bound(a,a+n+1,sa[S[i][j]])-a-1;
vis[x]=1;
}int count=0;
for(int j=0;j<n;j++)if(vis[j])count++;
if(count>=n)return 1;
}
}return 0;
}
void Print(int L){
int cur=-1;
for(int i=1;i<=u;i++){
if(h[i]<L)S[++cur].clear();
S[cur].push_back(i);
}
for(int i=0;i<=cur;i++){
if(S[i].size()>=n){
memset(vis,0,sizeof(vis));
for(int j=0;j<S[i].size();j++){
int k=S[i][j];
int x=upper_bound(a,a+n+1,sa[S[i][j]])-a-1;
vis[x]=true;
}int count=0;
for(int j=0;j<n;j++)if(vis[j])count++;
if(count>=n){
for(int j=0;j<L;j++)printf("%c",char(s[sa[S[i][0]]+j]));
puts("");
return;
}
}
}
}int T;
int main(){
scanf("%d",&T);
while(T--){
scanf("%d",&n);
int tmp=200; u=0;
for(int i=0;i<n;i++){
scanf("%s",str);
len[i]=strlen(str);
for(int j=0;j<len[i];j++)s[u++]=(int)str[j];
s[u++]=tmp++;
}tmp=0; s[u]=0;
for(int i=0;i<=n;i++){
a[i]=tmp;
if(i<n)tmp=tmp+(i==0?len[i]:len[i]+1);
}suffixarray(u,5000);
int l=1,r=len[n-1],ans=0;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid))ans=mid,l=mid+1;
else r=mid-1;
}if(ans<3)puts("no significant commonalities");
else Print(ans);
}return 0;
}

  

POJ 3080 Blue Jeans(后缀数组+二分答案)的更多相关文章

  1. POJ 3080 Blue Jeans 后缀数组, 高度数组 难度:1

    题目 http://poj.org/problem?id=3080 题意 有m个(2<=m<=10)不包含空格的字符串,长度为60个字符,求所有字符串中都出现过的最长公共子序列,若该子序列 ...

  2. POJ 3080 Blue Jeans (后缀数组)

    题目大意: 求出这些DNA序列中的最长且字典序最小的公共子串. 思路分析: 二分长度的答案,去height中扫描这个长度是否满足,一旦满足就立即输出.这样就能够保证字典序最小了. #include & ...

  3. Poj 1743 Musical Theme(后缀数组+二分答案)

    Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 28435 Accepted: 9604 Descri ...

  4. Poj 3261 Milk Patterns(后缀数组+二分答案)

    Milk Patterns Case Time Limit: 2000MS Description Farmer John has noticed that the quality of milk g ...

  5. POJ 1226 Substrings(后缀数组+二分答案)

    [题目链接] http://poj.org/problem?id=1226 [题目大意] 求在每个给出字符串中出现的最长子串的长度,字符串在出现的时候可以是倒置的. [题解] 我们将每个字符串倒置,用 ...

  6. poj 3294 Life Forms - 后缀数组 - 二分答案

    题目传送门 传送门I 传送门II 题目大意 给定$n$个串,询问所有出现在严格大于$\frac{n}{2}$个串的最长串.不存在输出'?' 用奇怪的字符把它们连接起来.然后求sa,hei,二分答案,按 ...

  7. poj 3415 Common Substrings - 后缀数组 - 二分答案 - 单调栈

    题目传送门 传送点I 传送点II 题目大意 给定串$A, B$,求$A$和$B$长度大于等于$k$的公共子串的数量. 根据常用套路,用一个奇怪的字符把$A$,$B$连接起来,然后二分答案,然后按mid ...

  8. BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案

    BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案 Description          给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l        读入单 ...

  9. POJ 3080 Blue Jeans (求最长公共字符串)

    POJ 3080 Blue Jeans (求最长公共字符串) Description The Genographic Project is a research partnership between ...

随机推荐

  1. PHP MySql数据库访问

    PHP MySql数据库访问 计应134   凌豪 1.MySql数据库的连接 要操作MySql数据库,首先必须与MySQl数据库建立连接,连接MySQL服务器的语句如下: <?php$link ...

  2. 织梦list文章列表按权重排序

    织梦的文章列表按权重排序 DEDECMS(织梦)5.6系统支持文档权重weight排序,可以在模板中使用: {dede:arclist row='10' titlelen='50' orderby=' ...

  3. Cocos2d-x 安装教程for mac(Xcode)

    cocos2d v3.x 版本出来后,从配置安装到创建项目都是命令行,下面简单说一下. 1. 下载地址    http://cn.cocos2d-x.org/download/ (虽然没有标明 for ...

  4. SQL Server save transaction

    准备: create table Nums(X int); 目的:只向表中插入一行. --------------------------------------------------------- ...

  5. 第三届蓝桥杯预赛真题_第一题_两种微生物 X 和 Y

    /* 假设有两种微生物 X 和 Y X出生后每隔3分钟分裂一次(数目加倍),Y出生后每隔2分钟分裂一次(数目加倍). 一个新出生的X,半分钟之后吃掉1个Y,并且,从此开始,每隔1分钟吃1个Y. 现在已 ...

  6. [Leetcode][Python]23: Merge k Sorted Lists

    # -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 23: Merge k Sorted Listshttps://oj.leet ...

  7. OpenNebula openldap集成

    Preface: 当前写这篇post的心情可谓是即激动,又操蛋!............................ ruiy还是言归正传,人老了,赖的扯淡了,哥当前一心看向Tech(s),做个顾 ...

  8. paip.c++ qt 项目工程互相引用的方法

    paip.c++ qt 项目工程互相引用的方法 作者Attilax ,  EMAIL:1466519819@qq.com  来源:attilax的专栏 地址:http://blog.csdn.net/ ...

  9. 算法导论——lec 10 图的基本算法及应用

    搜索一个图是有序地沿着图的边訪问全部定点, 图的搜索算法能够使我们发现非常多图的结构信息, 图的搜索技术是图算法邻域的核心. 一. 图的两种计算机表示 1. 邻接表: 这样的方法表示稀疏图比較简洁紧凑 ...

  10. Android 开发佳站3

    eclipse 某些java文件乱码 摘要: [一篮饭特稀原创,转载请注明出自http://www.cnblogs.com/wanghafan/archive/2013/04/24/3040219.h ...