POJ3294--Life Forms 后缀数组+二分答案 大于k个字符串的最长公共子串
Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 10800 | Accepted: 2967 |
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 ? 题意: n个字符串, 求大于n/2个字符串的最长子串。 如果有多个按字典序输出。 大致思路:首先把所有字符串用不相同的一个字符隔开(用同一个字符隔开wa了好久), 这里我是用数字来隔开的。
然后依次求sa,lcp。 我们可以二分答案的长度, 对于长度x,我们可以把 后缀进行分组(lcp[i] < x时 隔开), 然后对于每一组判断有多少个字符串出现,如果大于n/2说明符合。。对于字典序就不用排序了,,因为我们就是按照sa数组来遍历lcp的。。所以直接得到的答案就是字典序从小到大。
#include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const double eps = 1e-;
const int M = 2e6+;
int s[M];
int sa[M], tmp[M], rank[M], lcp[M], k, len;
bool cmp(int i, int j)
{
if (rank[i] != rank[j])
return rank[i] < rank[j];
else
{
int x = i+k <= len ? rank[i+k] : -;
int y = j+k <= len ? rank[j+k] : -;
return x < y;
}
}
void build_sa()
{
for (int i = ; i <= len; i++)
{
sa[i] = i;
rank[i] = i < len ? s[i] : -;
}
for (k = ; k <= len; k *= )
{
sort (sa, sa+len+, cmp);
tmp[sa[]] = ;
for (int i = ; i <= len; i++)
{
tmp[sa[i]] = tmp[sa[i-]] + (cmp(sa[i-], sa[i]) ? : );
}
for (int i = ; i <= len; i++)
{
rank[i] = tmp[i];
}
}
}
void Get_Lcp()
{
for (int i = ; i < len; i++)
{
rank[sa[i]] = i;
}
int h = ;
lcp[] = ;
for (int i = ; i < len; i++)
{
int j = sa[rank[i]-];
if (h > )
h--;
for (; i+h < len && j+h < len; h++)
if (s[i+h] != s[j+h])
break;
lcp[rank[i]] = h;
}
}
int vis[], pos[M];
int ans[M], tot;
int Stack[M], top;
bool solve (int x, int n)
{
int minv = inf;
int cnt = ;
bool flag = false;
for (int i = ; i <= len+; i++)
{
if (lcp[i] < x)
{ if ( cnt+ (!vis[pos[sa[i-]]]) > n/ && (minv != inf && minv >= x))
{
if (!flag )
tot = ;
flag = true;
ans[tot++] = sa[i-];
}
minv = inf;
cnt = ;
memset(vis, , sizeof (vis));
continue;
}
if ( vis[pos[sa[i-]]]==)
{
cnt++; }
vis[pos[sa[i-]]] = ;
minv = min(minv, lcp[i]); }
return tot > && flag;
}
int string_len[], c1;
void init()
{
c1 = tot = ;
memset(vis, , sizeof (vis));
memset(string_len, , sizeof (string_len));
}
char cacaca[];
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
// freopen("wa.txt","w",stdout);
#endif
int n, cas = ;
while ( scanf ("%d", &n), n)
{
if (cas != )
printf("\n");
cas++;
init();
len = ;
int del = ;
for (int i = ; i < n; i++)
{
scanf ("%s", cacaca);
int sub_len = strlen(cacaca);
for (int j = ; j < sub_len; j++)
{
s[len++] = cacaca[j];
}
s[len++] = M+del;
del++;
string_len[c1] = sub_len + string_len[c1-];
if (c1)
string_len[c1]++;
c1++;
}
if (n == )
{
for (int i = ; i < len-; i++)
{
printf("%c", s[i]);
}
continue;
}
for (int i = , j = ; i < len; i++)
{
if (i >= string_len[j])
{
pos[i] = -;
j++;
continue;
}
pos[i] = j+;
}
build_sa();
Get_Lcp(); int ua = , ub = M;
while (ua + < ub)
{
int mid = (ua + ub) >> ;
if (mid&&solve(mid, n) == true)
{ ua = mid;
}
else
ub = mid;
}
if (tot == )
printf("?\n");
else
{
if (ua == )
{
printf("?\n");
continue;
}
for (int i = ; i < tot; i++)
{
for (int j = ans[i]; j < ans[i]+ua; j++)
{
printf("%c", s[j]);
}
printf("\n");
}
}
}
return ;
}
POJ3294--Life Forms 后缀数组+二分答案 大于k个字符串的最长公共子串的更多相关文章
- POJ 3294 Life Forms 后缀数组+二分 求至少k个字符串中包含的最长子串
Life Forms Description You may have wondered why most extraterrestrial life forms resemble humans, ...
- poj 3294 Life Forms - 后缀数组 - 二分答案
题目传送门 传送门I 传送门II 题目大意 给定$n$个串,询问所有出现在严格大于$\frac{n}{2}$个串的最长串.不存在输出'?' 用奇怪的字符把它们连接起来.然后求sa,hei,二分答案,按 ...
- 【poj3294-不小于k个字符串中最长公共子串】后缀数组
1.注意每两个串之间的连接符要不一样. 2.分组的时候要注意最后一组啊!又漏了! 3.开数组要考虑连接符的数量.100010是不够的至少要101000. #include<cstdio> ...
- POJ 3080 Blue Jeans(后缀数组+二分答案)
[题目链接] http://poj.org/problem?id=3080 [题目大意] 求k个串的最长公共子串,如果存在多个则输出字典序最小,如果长度小于3则判断查找失败. [题解] 将所有字符串通 ...
- BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案
BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案 Description 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l 读入单 ...
- Poj 1743 Musical Theme(后缀数组+二分答案)
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 28435 Accepted: 9604 Descri ...
- Poj 3261 Milk Patterns(后缀数组+二分答案)
Milk Patterns Case Time Limit: 2000MS Description Farmer John has noticed that the quality of milk g ...
- POJ2774 Long Long Message —— 后缀数组 两字符串的最长公共子串
题目链接:https://vjudge.net/problem/POJ-2774 Long Long Message Time Limit: 4000MS Memory Limit: 131072 ...
- cogs249 最长公共子串(后缀数组 二分答案
http://cogs.pro:8080/cogs/problem/problem.php?pid=pxXNxQVqP 题意:给m个单词,让求最长公共子串的长度. 思路:先把所有单词合并成一个串(假设 ...
随机推荐
- Jetty开发指导:框架
Spring设置 你能嵌入Jetty到你的项目中,也能够使用差点儿全部的IoC类型框架,包含Spring.假设全部你想做的是在你的Spring中设置Jetty Server,那么以下的xml片段能够作 ...
- 几个常用的ps命令
1. ps aux If you are looking for a short summary of the active processes, use ps aux [root@rhel7 tm ...
- linux定时任务2-at命令
定时执行命令: [root@rheltest1 ~]# at now + 1 minute //一分钟后执行下面的任务 at> date >> /tmp/test_date.log ...
- mysql source命令导入sql文件效率分析和索引整理
Query OK, 24918 rows affected (0.90 sec)Records: 24918 Duplicates: 0 Warnings: 0 Query OK, 24923 r ...
- 用CSS边框图像让你的网站更漂亮
不久之前,添加一些装饰性元素,例如给网页中的图片添加花哨的边,以及耐心调整CSS文件才能使你的网页看起来不错.然而现在CSS已经做出了改变,用复杂的边框装饰你的网站只需几行代码.这篇文章将告诉你如何做 ...
- C#里巧用DateTime预设一些可选的日期范围(如本年度、本季度、本月等)
//大家在做报表或查询的时候都会有给用户预设一些可选的日期范围(如上图) //如本年度销售额.本季度利润.本月新增客户 //C#里内置的Da ...
- Microsoft Office 2007 Professional Plus+ 正版密钥
Microsoft Office 2007 Professional Plus+ 正版密钥 说微软原版,自有Microsoft官方MSDN网站有关下载的校验值为证(附后).密钥安装后 ...
- 解析xml的几种方式
http://blog.csdn.net/smcwwh/article/details/7183869
- 修改SELinux设置,使vsftp在enforcing security enhance模式下正常运行
开了SELinux和防火墙,没想到引出了vsftp的问题.FTP登录报错:500 OOPS: cannot change directory.下面来看看产生这个问题的原因和对策. 首先,分析一下冲突原 ...
- Win7系统安装MySQL
最近重装系统,重新搭建编译环境:重装mysql,发现一篇特别好的安装博客(http://blog.csdn.net/longyuhome/article/details/7913375),转载过来,留 ...