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)
关于解法这个讲的很清楚了,主要用了设关键点的巧妙思想. 主要想说的是一个刚学的方法:通过后缀自动机建立后缀树,再转成后缀数组. 后缀数组功能强大,但是最令人头疼的地方是模板太难背容易写错.用这个方法, ...
随机推荐
- appium + python 自动化调试手机时 UiAutomator exited unexpectedly with code 0, signal null
放上appium报错图,appium在手机里安装了appium setting 和unlock 软件,输入法也被变成了appium input ,但是就是点不到目标软件,手机也可以被cmd adb ...
- SQL语句中exists和in的区别
转自https://www.cnblogs.com/liyasong/p/sql_in_exists.html 和 http://blog.csdn.net/lick4050312/article/d ...
- python函数基础(函数的定义和调用)
函数的定义 python定义函数使用def关键字 return[表达式]语句用于退出函数,选择性的向调用方返回一个表达式,不带参数值的return语句返回none def 函数名(参数列表): 函数体 ...
- eclipse 克隆 https 地址的 Git 仓库报错:cannot open git-upload-pack
解决方法:Window >Preferences >Team>Git>User settings点击Add Entry设置key:http.sslVerify value:fa ...
- JS流程控制语句 重复重复(for循环)语句结构: for(初始化变量;循环条件;循环迭代) { 循环语句 }
重复重复(for循环) 很多事情不只是做一次,要重复做.如打印10份试卷,每次打印一份,重复这个动作,直到打印完成.这些事情,我们使用循环语句来完成,循环语句,就是重复执行一段代码. for语句结构: ...
- npm淘宝镜像配置
npm config set registry https://registry.npm.taobao.org
- ssm框架,出现xxx不能加载,或者bean不能加载时的解决方案之一
有可能是你在项目的mapper.xml文件中添加了本项目没有的实体类, 你把日志中找不到的最后一个实体类全项目搜索下,改成本项目可以引用的即可
- Windows下运行Tomcat闪退问题
直接双击startup.bat后闪退,可能的原因是tomcat的配置没有完全正确 完整的tomcat的配置应该配置: 1.JAVA_HOME 2.CATALINA_HOME 3.Path:%CATAL ...
- C#用API可以改程序名字
[DllImport("user32.dll", EntryPoint = "FindWindow")] public static extern int Fi ...
- ValueError: Variable conv1/weights already exists.
跑TensorFlow程序的过程中出现了错误,解决之后再次跑时,报如下错误: ValueError: Variable conv1/weights already exists, 原因: 这是因为我在 ...