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)
关于解法这个讲的很清楚了,主要用了设关键点的巧妙思想. 主要想说的是一个刚学的方法:通过后缀自动机建立后缀树,再转成后缀数组. 后缀数组功能强大,但是最令人头疼的地方是模板太难背容易写错.用这个方法, ...
随机推荐
- C# 字符串string和内存流MemoryStream及比特数组byte[]之间相互转换
定义string变量为str,内存流变量为ms,比特数组为bt 1.字符串转比特数组 复制代码 代码如下: (1)byte[] bt=System.Text.Encoding.Default.GetB ...
- SHELL递归遍历文件夹下所有文件
#!/bin/bash read_dir(){ ` do "/"$file ] then if [[ $file != '.' && $file != '..' ] ...
- VS2017+QT5.12环境配置与动态链接库的生成
最近需要重新编译一个DLL动态链接库,由于源码中包含了QT代码,所以现在需要配置VS+QT环境. 本人系统环境:Win10 64位 一.安装 Visual Studio 2017软件下载安装教程:ht ...
- NOIP2018游记 & 退役记
NOIP2018游记 & 退役记 我是一名来自湖北武汉华中师大一附中的高二\(OIer\),学习\(OI\)一年,今年去参加\(NOIP\),然后退役.这是一篇\(NOIP2018\)的游记, ...
- C++: Type conversions
1.static_cast static_cast可以转换相关联的类,可以从子类转换成父类.也能从父类转向子类,但是如果转换的父类指针(或者父类引用)所指向的对象是完整的,那么是没有问题:但是 ...
- loj6247 九个太阳
题意: k<=2^20,n<=10^15. 标程: #include<cstdio> using namespace std; typedef long long ll; ; ...
- 转载:Linux命令经典面试题:统计文件中出现次数最多的前10个单词
1.使用linux命令或者shell实现:文件words存放英文单词,格式为每行一个英文单词(单词可以重复),统计这个文件中出现次数最多的前10个单词 主要考察对sort.uniq命令的使用,相关解释 ...
- 廖雪峰Java13网络编程-3其他-2RMI远程调用
1.RMI远程调用: Remote Method Invocation 目的:把一个接口方法暴露给远程 示例: 定义一个接口Clock,它有一个方法能够获取当前的时间,并编写一个实现类,来实现这个接口 ...
- 「题解」:[AHOI2013]作业
问题: 作业 时间限制: 10 Sec 内存限制: 512 MB 题面 题目描述 此时己是凌晨两点,刚刚做了Codeforces的小A掏出了英语试卷.英语作业其实不算多,一个小时刚好可以做完.然后是 ...
- 「题解」:[POJ2942]Knights of the Round Table
问题 E: Knights of the Round Table 时间限制: 1 Sec 内存限制: 256 MB 题面 题目描述 作为一名骑士是一个非常有吸引力的职业:寻找圣杯,拯救遇难的少女,与 ...