UVA11107 Life Forms SA模板
Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 16827 | Accepted: 4943 |
Description
You may have wondered why most extraterrestrial life forms resemble humans, differing by superficial traits such as height, colour, wrinkles, ears, eyebrows and the like. A few bear no human resemblance; these typically have geometric or amorphous shapes like cubes, oil slicks or clouds of dust.
The answer is given in the 146th episode of Star Trek - The Next Generation, titled The Chase. It turns out that in the vast majority of the quadrant's life forms ended up with a large fragment of common DNA.
Given the DNA sequences of several life forms represented as strings of letters, you are to find the longest substring that is shared by more than half of them.
Input
Standard input contains several test cases. Each test case begins with 1 ≤ n ≤ 100, the number of life forms. n lines follow; each contains a string of lower case letters representing the DNA sequence of a life form. Each DNA sequence contains at least one and not more than 1000 letters. A line containing 0 follows the last test case.
Output
For each test case, output the longest string or strings shared by more than half of the life forms. If there are many, output all of them in alphabetical order. If there is no solution with at least one letter, output "?". Leave an empty line between test cases.
Sample Input
3
abcdefg
bcdefgh
cdefghi
3
xxx
yyy
zzz
0
Sample Output
bcdefg
cdefgh ?
Source
【题解】
UVA炸了,在POJ上交的
把所有的串连起来,串尾加分隔符,一来识别串尾,二来防止跟后面的串拼起来一块与其他串组成LCP,分组时会出现错误
二分答案分组,看每个组里是否有大于n/2个串即可
细节很多,关键是要输出方案。。。还要做很鬼畜的标记,各种判断标识符。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
#define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
template <class T>
inline void swap(T& a, T& b)
{
T tmp = a;a = b;b = tmp;
}
inline void read(int &x)
{
x = ;char ch = getchar(), c = ch;
while(ch < '' || ch > '') c = ch, ch = getchar();
while(ch <= '' && ch >= '') x = x * + ch - '', ch = getchar();
if(c == '-') x = -x;
}
const int INF = 0x3f3f3f3f;
const int MAXN = + ;
struct SuffixArray
{
char s[MAXN];int sa[MAXN], t1[MAXN], t2[MAXN], rank[MAXN], height[MAXN], c[MAXN], n;
void clear(){n = ;memset(sa, , sizeof(sa));}
void build_sa(int m)
{
int i, *x = t1, *y = t2;
for(i = ;i <= m;++ i) c[i] = ;
for(i = ;i <= n;++ i) ++ c[x[i] = s[i]];
for(i = ;i <= m;++ i) c[i] += c[i - ];
for(i = n;i >= ;-- i) sa[c[x[i]] --] = i;
for(int k = ;k <= n;k <<= )
{
int p = ;
for(i = n - k + ;i <= n;++ i) y[++ p] = i;
for(i = ;i <= n;++ i) if(sa[i] > k) y[++ p] = sa[i] - k;
for(i = ;i <= m;++ i) c[i] = ;
for(i = ;i <= n;++ i) ++ c[x[y[i]]];
for(i = ;i <= m;++ i) c[i] += c[i - ];
for(i = n;i >= ;-- i) sa[c[x[y[i]]] --] = y[i];
swap(x, y);p = ,x[sa[]] = ++ p;
for(i = ;i <= n;++ i) x[sa[i]] = sa[i] + k <= n && sa[i - ] + k <= n && y[sa[i]] == y[sa[i - ]] && y[sa[i] + k] == y[sa[i - ] + k] ? p : ++ p;
if(p >= n) break;m = p;
}
}
void build_height()
{
int i,j,k = ;
for(i = ;i <= n;++ i) rank[sa[i]] = i;
for(i = ;i <= n;++ i)
{
if(k) -- k; if(rank[i] == ) continue;
j = sa[rank[i] - ];
while(i + k <= n && j + k <= n && s[i + k] == s[j + k]) ++ k;
height[rank[i]] = k;
}
}
}A;
int cnt, n, tmp, ans, num[MAXN], vis[MAXN], tt = ;
std::vector<int> node;
int check(int x)
{
int num = , flag = , t = , f = ;
for(int i = ;i <= n;++ i)
{
if(A.s[A.sa[i]] == 'z' + || A.s[A.sa[i - ]] == 'z' + || ::num[A.sa[i] + x] != ::num[A.sa[i]] || ::num[A.sa[i - ] + x] != ::num[A.sa[i - ]])
{
num = , ++ tt, t = , f = ;
continue;
}
if(A.height[i] >= x)
{
if(t)
{
t = ;
vis[::num[A.sa[i - ]]] = tt;
++ num;
}
if(vis[::num[A.sa[i]]] == tt) continue;
++ num, vis[::num[A.sa[i]]] = tt;
}
else num = , ++ tt, t = , f = ;
if(num >= cnt/ + && f)
{
if(!flag) node.clear();
node.push_back(i);
f = ;
flag =;
}
}
return flag;
}
void put()
{
for(int i = ;i < node.size();++ i)
{
for(int j = A.sa[node[i]], k = ;k <= ans;++ k, ++ j)
printf("%c", A.s[j]);
putchar('\n');
}
}
int main()
{
while(scanf("%d", &cnt) != EOF && cnt)
{
if(cnt == )
{
scanf("%s", A.s + );
printf("%s\n\n", A.s + );
continue;
}
A.clear();n = ;tmp = ;
for(int i = ;i <= cnt;++ i)
{
scanf("%s", A.s + n + );
int t = n + ;
tmp = max(tmp, strlen(A.s + n + ));
n += strlen(A.s + n + );
A.s[++ n] = 'z' + ;
for(int j = t;j <= n;++ j) num[j] = i;
}
A.n = n;
A.build_sa('z' + );
A.build_height();
int l = , r = tmp, mid;ans = ;
while(l <= r)
{
mid = (l + r) >> ;
if(check(mid)) l = mid + , ans = mid;
else r = mid - ;
}
if(ans) put();
else printf("?\n");
putchar('\n');
}
return ;
}
UVA11107
UVA11107 Life Forms SA模板的更多相关文章
- UVA11107 Life Forms --- 后缀数组
UVA11107 Life Forms 题目描述: 求出出现在一半以上的字符串内的最长字符串. 数据范围: \(\sum len(string) <= 10^{5}\) 非常坑的题目. 思路非常 ...
- UVA-11107 Life Forms(后缀数组)
题目大意:给出n个字符串,找出所有最长的在超过一半的字符串中出现的子串. 题目分析:将所有的字符串连成一个,二分枚举长度,每次用O(n)的时间复杂度判断.连接字符串的时候中间添一个没有出现过的字符. ...
- UVA11107 Life Forms
思路 后缀数组 先都拼在一起 二分+height分段 按照小于x的为分界,判断是否有一个分段中包含超过n/2个串 代码 #include <cstdio> #include <cst ...
- 【POJ3294】 Life Forms(SA)
...又是TLE,对于单组数据肯定TLE不了,问题是多组的时候就呵呵了... 按height分组去搞,然后判一下是否不属于同一个串... ; var x,y,rank,sa,c,col,h,rec:. ...
- SA模板
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; ; char ...
- UVA-11107 Life Forms(求出现K次的子串,后缀数组+二分答案)
题解: 题意: 输入n个DNA序列,你的任务是求出一个长度最大的字符串,使得它在超过一半的DNA序列中出现.如果有多解,按照字典序从小到大输入所有解. 把n个DNA序列拼在一起,中间用没有出现过的字符 ...
- 洛谷3809 SA模板 后缀数组学习笔记(复习)
其实SA这个东西很久之前就听过qwq 但是基本已经忘的差不多了 嘤嘤嘤 QWQ感觉自己不是很理解啊 所以写不出来那种博客 QWQ只能安利一些别人的博客了 小老板 真的是讲的非常好 不要在意名字 orz ...
- Visual Studio项目模板与向导开发
在[Xamarin+Prism开发详解系列]里面经常使用到[Prism unity app]的模板创建Prism.Forms项目: 备注:由于Unity社区已经不怎么活跃,下一个版本将会有Autofa ...
- [BZOJ4650][NOI2016]优秀的拆分(SAM构建SA)
关于解法这个讲的很清楚了,主要用了设关键点的巧妙思想. 主要想说的是一个刚学的方法:通过后缀自动机建立后缀树,再转成后缀数组. 后缀数组功能强大,但是最令人头疼的地方是模板太难背容易写错.用这个方法, ...
随机推荐
- 2_2.springboot2.x配置之自动配置原理
前言 SpringBoot 自动配置原理: 本文主要分为三大部分: SpringBoot 源码常用注解 SpringBoot 启动过程 SpringBoot 自动配置原理 1. SpringBoot ...
- USACO 2009 Open Grazing2 /// DP+滚动数组oj26223
题目大意: 输入n,s:n头牛 s个栅栏 输入n头牛的初始位置 改变他们的位置,满足 1.第一头与最后一头的距离尽量大 2.相邻两头牛之间的距离尽量满足 d=(s-1)/(n-1),偏差不超过1 3. ...
- matlab之原始处理图像几何变换
(一)图像几何变换理论知识 (1)图像的平移与比例 图像的平移很简单,平移前后的坐标分别为(x,y)和(x',y'),则满足的关系式为 x'= x +Tx: y'= y +Ty: 其中Tx与Ty分别为 ...
- IDA*算法——骑士精神
例题 骑士精神 Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位.在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者 ...
- pytorch 入门指南
两类深度学习框架的优缺点 动态图(PyTorch) 计算图的进行与代码的运行时同时进行的. 静态图(Tensorflow <2.0) 自建命名体系 自建时序控制 难以介入 使用深度学习框架的优点 ...
- linux 每天一个命令
Nginx [emerg]: bind() to 0.0.0.0:80 failed (98: Address already in use) 使用命令关闭占用80端口的程序 sudo fuser ...
- badboy的录制和jmeter的使用
v Jmeter是什么 Apache Jmeter是Apache组织开发的基于Java的压力测试工具. Jmeter可以用于对服务器.网络或对象模拟巨大的负载,来自不同压力类别下测试它们的强度和分析 ...
- mybatis-环境配置-基本案例-和hibernate区别
Mybatis第一天 1. Mybatis介绍 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了goo ...
- Ubuntu时间管理方法
1. date 命令主要用于显示以及修改系统时间 2. hwclock 命令用于查看设置硬件时间,以及同步硬件时间与系统时间 # 显示硬件时间hwclock # 设置硬件时间hwclock -set ...
- deepfake安装python常用命令
pip install -r requirements.txt -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple/ python -m p ...