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个单词,让求最长公共子串的长度. 思路:先把所有单词合并成一个串(假设 ...
随机推荐
- struts2在web.xml中配置详情
web.xml是web应用中载入有关servlet信息的重要配置文件,起着初始化servlet,filter等web程序的作用. 通常,全部的MVC框架都须要Web应用载入一个核心控制器.那採取什么方 ...
- easyui 给文本框 checkbox赋值问题
刚进公司 要做一个后台维护系统,选择easyui 从未接触过 对于页面给文本框赋值遇到一些问题 写下了来 我之前使用了好几种方式都未能成功给input 文本框赋值 第一尝试传统的JavaScript代 ...
- UVa 340 Master-Mind Hints (优化查找&复制数组)
340 - Master-Mind Hints Time limit: 3.000 seconds http://uva.onlinejudge.org/index.php?option=com_on ...
- Android学习四、Android中的Adapter
一.Adapter的介绍 An Adapter object acts as a bridge between an AdapterView and the underlying data for t ...
- SWFObject文件上传使用记录
SWFObject文件上传使用方法记录,该插件使用起来相当强大也很灵活,与uploadify各有千秋. 值得一说的是,如果要设置button_image_url这个参数,该参数是按钮的背景图,但是一定 ...
- linux nohup命令
nohup 命令 用途:不挂断地运行命令.如果你正在执行一个job,并且你希望在退出帐户/关闭终端之后继续运行,可以使用nohup命令.nohup就是不挂起的意思( no hang up). 语法:n ...
- sql 常用语法汇总
Sql常用语法 SQL分类: DDL—数据定义语言(CREATE,ALTER,DROP,DECLARE) DML—数据操纵语言(SELECT,DELETE,UPDATE,INSERT) DCL—数据控 ...
- Git系列(1) Windows下Git服务器搭建
作为对前两天Git服务器搭建的一个整理,我想分别从服务端和客户端两个角度来记录下整个搭建过程,为了达到目标,我们需要哪些操作. (一)服务端软件和账号的安装配置 我们这里只需要两个软件git和ssh, ...
- RecyclerView更通用——listView的onItemClick,onLongItemClick,addHeaderView,addFooterView
一.点击事件 setOnItemClickListener,setOnItemLongClickListener RecyclerView中虽然没有提供上面这两个接口,但是给我们提供了另外一个接口:O ...
- 解决Cacti监控图像断断续续问题
最近cacti的图像全都是断断续续.新加的设备,图像也是这样,查看cacti 的log发现大量下面类似的错误信息:04/12/2011 03:54:37 PM - SPINE: Poller[0] H ...