【POJ No. 3294】星际迷航 Life Forms

北大OJ 题目地址

【题意】

你可能想知道为什么大多数外星生命形式与人类相似,事实证明,绝大多数生命形式最终都是一个普通DNA的大片段。在几种生命形式的DNA序列中,找出由超过一半的生命形式共享的最长子串。

【输入输出】

输入:

输入包含几个测试用例。每个测试用例的第,行都包含N(1≤N ≤100),表示生命形式的数量。接下来的N 行,每行都包含一个字符串,表示生命形式的DNA序列。每个DNA序列都包含至少1个且不超过1000个小写字母。最后一个测试用例之后的一行为0。

输出:

对每个测试用例,都单行输出超过一半生命形式共享的最长子串。若有很多,则按字母顺序输出所有子串。若没有解决方案,则输出“?”。在测试用例之间留一空行。

【样例】

【思路分析】

这道题包括多个字符串,求解至少重复N /2次的最长公共子串。首先用一个原字符串中没有的特殊字符将每个字符串都连接起来,求解至少重复N /2次的最长子串。可采用后缀数组及二分法求解。注意:对最长公共子串问题,除用特殊字符连接外,还要标记每个字符都属于哪一个字符串,这样才可以判断两个公共前缀是否属于同一个字符串的子串。

【算法设计】

① 将N 个字符串连接起来,中间以特殊字符间隔。

② 求解sa数组。

③ 求解rank数组和height数组。

④ 采用二分法求解,对特定的长度mid,判断满足height[i]≥mid的字符串个数是否大于或等于N /2,求出最大mid后,输出长度大于或等于mid的所有子串。

【算法实现】

#include<cstdio>
#include<string.h>
#include<cstring>
#include<algorithm>using namespace std;const int maxn=100500;
int n,k;
char s[maxn];
int belong[maxn];//属于哪一个字符串
int r[maxn],sa[maxn],rank[maxn],height[maxn];;
int wa[maxn],wb[maxn],wv[maxn],c[maxn];//c[]用于基数排序统计,如果写成maxm=500,则提示Runtime Error,中间结果可能溢出 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 *sa,int n,int m){int i,k,p,*x=wa,*y=wb;for(i=0;i<m;i++) c[i]=0;for(i=0;i<n;i++) c[x[i]=r[i]]++;for(i=1;i<m;i++) c[i]+=c[i-1];for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;for(k=1;k<=n;k<<=1){p=0;for(i=n-k;i<n;i++) y[p++]=i;//补零的位置下标排在最前面 for(i=0;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k;//基数排序第一关键字for(i=0;i<n;i++)wv[i]=x[y[i]];//将第二关键字排序结果转换为名次,进行排序 for(i=0;i<m;i++)c[i]=0;for(i=0;i<n;i++)c[wv[i]]++;for(i=1;i<m;i++)c[i]+=c[i-1];for(i=n-1;i>=0;i--)sa[--c[wv[i]]]=y[i];swap(x,y);p=1,x[sa[0]]=0;for(i=1;i<n;i++)x[sa[i]]=cmp(y,sa[i-1],sa[i],k)?p-1:p++;if(p>=n)//排序结束 break;m=p;}
}void calheight(int *r,int *sa,int n){int i,j,k=0;for(i=1;i<=n;i++)rank[sa[i]]=i;for(i=0;i<n;i++){if(k)k--;j=sa[rank[i]-1];while(r[i+k]==r[j+k])k++;height[rank[i]]=k;}
}bool check(int mid,int n,int m,int flag){int i=2;bool vis[105];while(1){memset(vis,0,sizeof(vis));//清零 while(i<=n&&height[i]<mid)i++;if(i>n)break;vis[belong[sa[i-1]]]=1;//标记该字符串 while(i<=n&&height[i]>=mid){vis[belong[sa[i]]]=1;i++;}int cnt=0;for(int j=1;j<=m;j++)if(vis[j])cnt++;if(cnt>m/2){if(!flag)return 1;else{for(int j=sa[i-1],t=0;t<mid;j++,t++)printf("%c",s[j]);printf("\n");}}}return 0;
}void solve(int L,int R){int res=-1,mid;while(L<=R){mid=(L+R)>>1;if(check(mid,n,k,0)){res=mid;L=mid+1;}elseR=mid-1;}if(res==-1)printf("?\n");elsecheck(res,n,k,1);//输出
}int main(){int len=0;while(scanf("%d",&k),k){memset(s,0,sizeof(s));n=0;for(int i=1;i<=k;i++){//将k个字符串连接起来,中间用特殊字符间隔 scanf("%s",s+n);if(i==1)len=strlen(s);for(;s[n]!='\0';n++){belong[n]=i;//标记属于第i个字符串 r[n]=s[n]-'a'+1;}s[n]='#';r[n]=100+i;n++;}n--;r[n]=0;da(r,sa,n+1,300);calheight(r,sa,n);solve(1,len);printf("\n");}return 0;
}

【POJ No. 3294】星际迷航 Life Forms相关推荐

  1. POJ - 3294 Life Forms(二分+后缀数组)

    题目链接:点击查看 题目大意:给出n个字符串,求出至少在n/2个字符串中出现的最长的公共子串,如果没有,输出"?" 题目分析:和poj3450几乎一样的题目,只不过最长公共子串出现 ...

  2. POJ题目分类(按初级\中级\高级等分类,有助于大家根据个人情况学习)

    本文来自:http://www.cppblog.com/snowshine09/archive/2011/08/02/152272.spx 多版本的POJ分类 流传最广的一种分类: 初期: 一.基本算 ...

  3. POJ 3237 Tree (树链剖分)

    Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 2825   Accepted: 769 Description ...

  4. POJ 3237.Tree -树链剖分(边权)(边值更新、路径边权最值、区间标记)贴个板子备忘...

    Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 12247   Accepted: 3151 Descriptio ...

  5. [Poj 1459] 网络流(一) {基本概念与算法}

    { 凸包的内容还欠整理 先来侃侃一个月以前就想写写的网络流 本文介绍网络流 网络流的算法 及其应用 这些问题没事想想还是很有意思的 } ================================ ...

  6. POJ 1417 True Liars 并查集+背包

    题目链接:http://poj.org/problem?id=1417 解题思路:比较容易想到的是并查集,然后把第三组数据测试一下之后发现这并不是简单的并查集,而是需要合并之后然后判断的.并且鉴于题目 ...

  7. POJ ZOJ题目分类

    POJ,ZOJ题目分类(多篇整合版,分类很细致,全面) 标签: 题目分类POJ整理 2015-04-18 14:44 1672人阅读 评论(0) 收藏 举报 本文章已收录于: 分类: ACM资料(5) ...

  8. POJ,ZOJ题目分类(多篇整合版,分类很细致,全面)

    水题: 3299,2159,2739,1083,2262,1503,3006,2255,3094 初级: 一.基本算法:        (1)枚举 (1753,2965)       (2)贪心(13 ...

  9. 【POJ 1286】Necklace of Beads(polya定理)

    [POJ 1286]Necklace of Beads(polya定理) Necklace of Beads Time Limit: 1000MS   Memory Limit: 10000K Tot ...

  10. POJ 3268 D-Silver Cow Party

    http://poj.org/problem?id=3268 Description One cow from each of N farms (1 ≤ N ≤ 1000) conveniently ...

最新文章

  1. 1.3 选择适合的Arduino
  2. Maven项目配置EL表达式原样输出解决方法
  3. datanode 不能连接master
  4. EventBus的简单使用
  5. Python实战系列之调用小黄鸡simsimi
  6. C语言 | 基于DS1302 的万年历实现
  7. 脉冲宽度调制pdm_0-500V可调0-30A高频脉冲电源广元厂家
  8. 6号团队-团队任务4:每日立会(2018-11-28)
  9. Android开发遇到手机无法弹出Toast
  10. command exec make executable file not found in %PATH%
  11. 04-Mysql----初识sql语句
  12. css3 animate 和关键帧 @-webkit-keyframes
  13. SpringBoot(十六)_springboot整合JasperReport6.6.0
  14. Git(10):删除远端仓库中多余文件(**.iml/target文件)
  15. php mysql网页象棋源码_C# 中国象棋 游戏源码
  16. 桌面计算机图标带虚线框,桌面图标出现虚线框,win10桌面图标带有虚线方框
  17. apache服务器的日志文件,apache日志文件在哪
  18. mysql强制修改root密码
  19. 升腾c10,华为ct3100安装nextcloud,KodExplorer网盘
  20. 楚留香服务器维护,【楚留香】4月20日维护公告

热门文章

  1. 转 适合wince初学者的一些 知识
  2. python append 字典_Python3中使用append添加字典元素出现问题
  3. PHP支付宝支付开发流程
  4. 如何使用计算机读文本,如何使用StrokeIt
  5. 微商史上最全软文标题写作套路(收藏版)
  6. Java经典全套面试汇总(二十万字)
  7. 如何使用Etcd来完成选举
  8. 计算机开机配置失败6,win7开机配置windows update失败怎么跳过?-win7配置update失败,安全模式还是配置失败...
  9. 服务器故障导致网站打不开,网站打不开的6种现象及解决方法
  10. python链家网爬虫_python3编写爬虫程序获取链家网租房信息