生命形式
时间限制: 5000MS   内存限制: 65536K
提交总数: 16660   接受: 4910

描述

你可能想知道为什么大多数外星人的生命形式与人类相似,不同的是表面特征,如身高,肤色,皱纹,耳朵,眉毛等等。有几个没有人类的相似之处; 这些通常具有几何形状或无定形形状,如立方体,浮油或灰尘云。

“ 星际迷航 ”第146集“ The Chase ” 给出了答案。事实证明,在这个象限的绝大多数生命形式中,共同DNA的一大片段结束了。

考虑到以字母串表示的几种生命形式的DNA序列,你应该找到一半以上的共享时间最长的子串。

输入

标准输入包含几个测试用例。每个测试用例始于1≤ Ñ ≤100,生命形式的数目。n行跟随; 每个都包含一串小写字母,代表生命形式的DNA序列。每个DNA序列包含至少一个但不超过1000个字母。最后一个测试用例后面是一行。

产量

对于每个测试用例,输出一半以上生命形式共享的最长的字符串或字符串。如果有多个,按字母顺序输出。如果至少有一个字母没有解决方案,输出“?”。在测试用例之间留下一条空行。

示例输入

3
ABCDEFG
bcdefgh
cdefghi
3
XXX
YYY
ZZZ
0

示例输出

bcdefg
cdefgh ?

类似双串匹配,我们将所有串通过一个间隔符链接起来,但要注意使用不同的间隔符,否则可能会将间隔符加入匹配【与双串不同,因为双串只有一个间隔符,无论如何也不会参与匹配】

之后我们常规二分答案,对于给定长度len,看看能否找到连续height都>=len且出现过的串的个数 >= N/2

最后我们得到ans,再进行一次查询,这次一找到直接输出

方法还是很直白,~~只是要考虑特判N = 1~~【不然会全部输出,直接OLE  QAQ】

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next)
using namespace std;
const int maxn = 100200,maxm = 100005,INF = 1000000000;
inline int RD(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
return out * flag;
}
char s[maxn],A[maxn];
int sa[maxn],rank[maxn],height[maxn],t1[maxn],t2[maxn],c[maxn],n,m,N,vis[105];
int id[maxn],len[maxn],Max;
void SA(){
int *x = t1,*y = t2;
for (int i = 0; i <= m; i++) c[i] = 0;
for (int i = 1; i <= n; i++) c[x[i] = s[i]]++;
for (int i = 1; i <= m; i++) c[i] += c[i - 1];
for (int i = n; i >= 1; i--) sa[c[x[i]]--] = i;
for (int k = 1; k <= n; k <<= 1){
int p = 0;
for (int i = n - k + 1; i <= n; i++) y[++p] = i;
for (int i = 1; i <= n; i++) if (sa[i] - k > 0) y[++p] = sa[i] - k;
for (int i = 0; i <= m; i++) c[i] = 0;
for (int i = 1; i <= n; i++) c[x[y[i]]]++;
for (int i = 1; i <= m; i++) c[i] += c[i - 1];
for (int i = n; i >= 1; i--) sa[c[x[y[i]]]--] = y[i];
swap(x,y);
p = 1; x[sa[1]] = 1;
for (int i = 2; i <= n; i++)
x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k]) ? p : ++p;
if (p >= n) break;
m = p;
}
for (int i = 1; i <= n; i++) rank[sa[i]] = i;
int k = 0;
for (int i = 1; i <= n; i++){
if (k) k--;
int j = sa[rank[i] - 1];
while (s[i + k] == s[j + k]) k++;
height[rank[i]] = k;
}
}
bool check(int K){
memset(vis,-1,sizeof(vis));
int flag = 0,cnt = 0;
for (int i = 1; i <= n; i++){
if (id[sa[i]] == -1){flag++; cnt = 1; continue;}
if (height[i] < K) cnt = 1,vis[id[sa[i]]] = ++flag;
else {if (vis[id[sa[i]]] != flag) ++cnt; vis[id[sa[i]]] = flag;}
if (cnt > N / 2) return true;
}
return false;
}
void getans(int K){
//cout<<K<<endl;
memset(vis,-1,sizeof(vis));
int flag = 0,cnt = 0,pos = sa[1],ok = true;
for (int i = 1; i <= n; i++){
if (id[sa[i]] == -1){flag++; cnt = 1; ok = true; pos = sa[i]; continue;}
if (height[i] < K) cnt = 1,vis[id[sa[i]]] = ++flag,ok = true,pos = sa[i];
else {if (vis[id[sa[i]]] != flag) ++cnt; vis[id[sa[i]]] = flag;}
if (cnt * 2 > N && ok){
ok = false;
for (int j = 0; j < K; j++) putchar(s[pos + j]);
puts("");
}
}
}
void solve(){
int l = 0,r = Max,mid;
while (l < r){
mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
if (!l) printf("?\n");
else getans(l);
printf("\n");
}
int main(){
while ((N = RD())){
if (N == 1){
scanf("%s",s + 1);
printf("%s\n\n",s + 1);
continue;
}
s[1] = '\0'; n = 0; m = 256; Max = -INF;
int tem,C = 0;
REP(i,N){
scanf("%s",A); tem = strlen(A); len[i] = n + tem; Max = max(Max,tem);
for (int j = 1; j <= tem; j++) id[n + j] = i; id[n + tem + 1] = -1;
strcat(s + 1,A); A[0] = ++C; A[1] = '\0'; strcat(s + 1,A);
n += tem + 1;
}
//REP(i,n) cout<<id[i];cout<<endl;
SA();
//for (int i = 2; i <= n; i++) cout<<height[i]<<' ';cout<<endl;
solve();
}
return 0;
}

POJ3294 Life Forms 【后缀数组】的更多相关文章

  1. POJ3294 Life Forms —— 后缀数组 最长公共子串

    题目链接:https://vjudge.net/problem/POJ-3294 Life Forms Time Limit: 5000MS   Memory Limit: 65536K Total ...

  2. POJ3294 Life Forms(后缀数组)

    引用罗穗骞论文中的话: 将n 个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开,求后缀数组.然后二分答案,用和例3 同样的方法将后缀分成若干组,判断每组的后缀是否出现在不小于k 个的原串中 ...

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

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

  4. Poj 3294 Life Forms (后缀数组 + 二分 + Hash)

    题目链接: Poj 3294 Life Forms 题目描述: 有n个文本串,问在一半以上的文本串出现过的最长连续子串? 解题思路: 可以把文本串用没有出现过的不同字符连起来,然后求新文本串的heig ...

  5. POJ 3294 UVA 11107 Life Forms 后缀数组

    相同的题目,输出格式有区别. 给定n个字符串,求最长的子串,使得它同时出现在一半以上的串中. 不熟悉后缀数组的童鞋建议先去看一看如何用后缀数组计算两个字符串的最长公共子串 Ural1517 这道题的思 ...

  6. POJ3294--Life Forms 后缀数组+二分答案 大于k个字符串的最长公共子串

                                                                              Life Forms Time Limit: 500 ...

  7. POJ 3294 Life Forms 后缀数组+二分 求至少k个字符串中包含的最长子串

    Life Forms   Description You may have wondered why most extraterrestrial life forms resemble humans, ...

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

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

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

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

  10. POJ3294 Life Forms(二分+后缀数组)

    给n个字符串,求最长的多于n/2个字符串的公共子串. 依然是二分判定+height分组. 把这n个字符串连接,中间用不同字符隔开,跑后缀数组计算出height: 二分要求的子串长度,判断是否满足:he ...

随机推荐

  1. 判断不同浏览器,加载不同的css和js文件

    在低版本的IE中,条件注释还有效果,但是在ie9,10,11浏览器中,条件注释不起作用. 在网上找了个校验ie的方法. function isIE(){  if (window.ActiveXObje ...

  2. django中的ContentType使用

    使用背景 最近设计表的时候遇到一个问题,有两门课程  一门专业课,一门学位课,我们按照时间长度来进行售卖,比如专业课一个月19元,两个月35元,三个月50元. 可以这么做但是领导不让我这么设计.... ...

  3. 关于JUnit4无法支持多线程测试的解决方法

    转自:https://segmentfault.com/a/1190000003762719 其实junit是将test作为参数传递给了TestRunner的main函数.并通过main函数进行执行. ...

  4. 剑指offer题目系列二

    本篇延续上一篇,介绍<剑指offer>第二版中的四个题目:从尾到头打印链表.用两个栈实现队列.旋转数组的最小数字.二进制中1的个数. 5.从尾到头打印链表 题目:输入一个链表的头结点,从尾 ...

  5. 一个适合变化的产品部署集成包(nginx+jdk+tomcat+nodejs+mysql+redis+mongo+MYSQL主主(读写分离)集群建立+代码包+持续上线+备份)

    一.前言 最近公司做了一套新产品,需要发布到不确定的硬件环境中(不同使用单位规模,使用人数,服务器提供的资源不同)若每次进行人工部署耗时费力,周期过长. 二.分析 具体的部署流程如下: 由上图流程进行 ...

  6. xss挑战赛小记 0x01(xsstest)

    0x00 今天在先知社区看到了一个xss挑战赛 结果发现比赛已经结束 服务器也关了 百度找了个xss挑战赛来玩一下 正好印证下xss的学习--- 地址     http://test.xss.tv/ ...

  7. leetcode笔记--3 Niim game

    question: You are playing the following Nim Game with your friend: There is a heap of stones on the ...

  8. iOS-合成图片(长图)

    合成图片 直接合成图片还是比较简单的,现在的难点是要把,通过文本输入的一些基本数据也合成到一张图片中,如果有多长图片就合成长图. 现在的实现方法是,把所有的文本消息格式化,然后绘制到一个UILable ...

  9. ExtJs4.1目录结构介绍和使用说明[转]

    一.在做ExtJs开发之前首先要到网站上下载ExtJs的开发包,我用的最新版本是4.1.1.此版本相对于之前的版本目录结构发生了一些变化,没有了adapter目录, 目录结构如下 文件/文件夹名的作用 ...

  10. MySQL用户权限控制一例

      Preface       I supposed we are encountering a situation that there's an anonymous user has connec ...