POJ 3294 Life Forms 后缀数组+二分 求至少k个字符串中包含的最长子串
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个串相连同样用一个没有出现过的字符间隔开来
只有两个相领的sa,lcp值是超过当前二分的md值并且 处于不同的串时才可当做两个数量
以此更新答案
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include<vector>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair
typedef long long LL;
const long long INF = 1e18+1LL;
const double Pi = acos(-1.0);
const int N = 2e5+, M = 2e5+, mod = 1e9+, inf = 2e9; ///heght[i] 表示 Suffix(sa[i-1])和Suffix(sa[i]) 的最长公共前缀:
///rank[i] 表示 开头为i的后缀的等级:
///sa[i] 表示 排名为i的后缀 的开头位置: int *rank,r[N],sa[N],height[N],wa[N],wb[N],wm[N];
bool cmp(int *r,int a,int b,int l) {
return r[a] == r[b] && r[a+l] == r[b+l];
} void SA(int *r,int *sa,int n,int m) {
int *x=wa,*y=wb,*t;
for(int i=;i<m;++i)wm[i]=;
for(int i=;i<n;++i)wm[x[i]=r[i]]++;
for(int i=;i<m;++i)wm[i]+=wm[i-];
for(int i=n-;i>=;--i)sa[--wm[x[i]]]=i;
for(int i=,j=,p=;p<n;j=j*,m=p){
for(p=,i=n-j;i<n;++i)y[p++]=i;
for(i=;i<n;++i)if(sa[i]>=j)y[p++]=sa[i]-j;
for(i=;i<m;++i)wm[i]=;
for(i=;i<n;++i)wm[x[y[i]]]++;
for(i=;i<m;++i)wm[i]+=wm[i-];
for(i=n-;i>=;--i)sa[--wm[x[y[i]]]]=y[i];
for(t=x,x=y,y=t,i=p=,x[sa[]]=;i<n;++i) {
x[sa[i]]=cmp(y,sa[i],sa[i-],j)?p-:p++;
}
}
rank=x;
}
void Height(int *r,int *sa,int n) {
for(int i=,j=,k=;i<n;height[rank[i++]]=k)
for(k?--k:,j=sa[rank[i]-];r[i+k] == r[j+k];++k);
} int n,id[N],all,pos[N],vis[N];
vector<string > A;
char str[][];
int check(int len) {
int i = , mx, mi,cnt = ,flag;
while() {
while(i <= n && height[i]< len) i++;
if(i > n) return ;
for(int j = ; j < all; ++j) vis[j] = ;
cnt = ;
flag = id[sa[i-]];
vis[flag] = ;
while(i <= n && height[i] >= len) {
if(!vis[id[sa[i]]])cnt++;
vis[id[sa[i]]] = ;
i++;
}
if(cnt > all/) return ;
}
return ;
}
void Output (int len) {
A.clear();
int i = ,cnt = ,flag,star;
while() {
while(i <= n && height[i] < len) i++;
if(i > n) break;
for(int j = ; j < all; ++j) vis[j] = ;
cnt = ;
flag = id[sa[i-]];
vis[flag] = ;
star = pos[sa[i-]];
while(i <= n && height[i] >= len) {
if(!vis[id[sa[i]]])cnt++;
vis[id[sa[i]]] = ;
i++;
}
if(cnt > all/) {
string now = "";
for(int j = star; j <= star + len - ; ++j) {
now += str[flag][j];
}
A.push_back(now);
}
}
sort(A.begin(),A.end());
for(int i = ; i < A.size(); ++i) cout<<A[i]<<endl;
}
int main() {
while(scanf("%d",&n)!=EOF) {
if(n == ) break;
for(int i = ; i < n; ++i) scanf("%s",str[i]);
all = n;
int cnt = , rr = ;
for(int i = ; i < n; ++i) {
rr = max(rr,(int )strlen(str[i]));
for(int j = ; str[i][j] != '\0'; ++j) {
id[cnt] = i;
pos[cnt] = j;
r[cnt++] = str[i][j] - 'a' + + ;
}
id[cnt] = i;
r[cnt++] = i;
}
r[--cnt] = ;
n = cnt;
SA(r,sa,n+,);
Height(r,sa,n);
// cout<<rr<<endl;
int ll = , ans = ;
while(ll <= rr) {
int md = (ll + rr) >> ;
if(check(md))
{
ans = md, ll = md + ;
}
else
{
rr = md - ;
}
}
if(ans == ) puts("?\n");
else {
Output(ans);
printf("\n");
}
}
return ;
}
POJ 3294 Life Forms 后缀数组+二分 求至少k个字符串中包含的最长子串的更多相关文章
- Poj 3294 Life Forms (后缀数组 + 二分 + Hash)
题目链接: Poj 3294 Life Forms 题目描述: 有n个文本串,问在一半以上的文本串出现过的最长连续子串? 解题思路: 可以把文本串用没有出现过的不同字符连起来,然后求新文本串的heig ...
- POJ3294--Life Forms 后缀数组+二分答案 大于k个字符串的最长公共子串
Life Forms Time Limit: 500 ...
- poj 3294 Life Forms - 后缀数组 - 二分答案
题目传送门 传送门I 传送门II 题目大意 给定$n$个串,询问所有出现在严格大于$\frac{n}{2}$个串的最长串.不存在输出'?' 用奇怪的字符把它们连接起来.然后求sa,hei,二分答案,按 ...
- POJ 1226 Substrings(后缀数组+二分答案)
[题目链接] http://poj.org/problem?id=1226 [题目大意] 求在每个给出字符串中出现的最长子串的长度,字符串在出现的时候可以是倒置的. [题解] 我们将每个字符串倒置,用 ...
- 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 ...
- poj 3261 Milk Patterns 后缀数组 + 二分
题目链接 题目描述 给定一个字符串,求至少出现 \(k\) 次的最长重复子串,这 \(k\) 个子串可以重叠. 思路 二分 子串长度,据其将 \(h\) 数组 分组,判断是否存在一组其大小 \(\ge ...
- POJ 3294 出现在至少K个字符串中的子串
在掌握POJ 2774(两个串求最长公共子串)以及对Height数组分组后,本题还是容易想出思路的. 首先用字符集外的不同字符连接所有串,这是为了防止两个后缀在比较时超过某个字符串的分界.二分子串的长 ...
- Poj 1743 Musical Theme (后缀数组+二分)
题目链接: Poj 1743 Musical Theme 题目描述: 给出一串数字(数字区间在[1,88]),要在这串数字中找出一个主题,满足: 1:主题长度大于等于5. 2:主题在文本串中重复出现 ...
随机推荐
- iis虚拟目录名称“ReportServer”的巧合
今天测试一个Crystal Report网站的报表服务,建立一个虚拟目录,名为ReportServer,结果无论怎样访问浏览器都返回 localhost/ReportServer - / Micr ...
- Thinking in java学习笔记之多态
多态是一种将改变的事物和未变的事物分离开来的重要技术.
- 【BZOJ-3507】通配符匹配 DP + Hash
3507: [Cqoi2014]通配符匹配 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 372 Solved: 156[Submit][Statu ...
- MongoDB Node.js driver
Node.js连接MongoDB的简单实例 安装Node.js driver npm install mongodb -save 连接 var MongodbClient = require('mon ...
- 前端模块化工具-webpack
详解前端模块化工具-webpack webpack是一个module bundler,抛开博大精深的汉字问题,我们暂且管他叫'模块管理工具'.随着js能做的事情越来越多,浏览器.服务器,js似乎无处不 ...
- java 判断String 是否为空
StringUtils.isBlank(null) = true StringUtils.isBlank("") = true StringUtils.isBlank(" ...
- [UML]UML系列——活动图activity diagram
系列文章 [UML]UML系列——用例图Use Case [UML]UML系列——用例图中的各种关系(include.extend) [UML]UML系列——类图Class [UML]UML系列——类 ...
- Bash 中的 $0 在什么时候不是 argv[0]
每个 C 程序都有一个 main 函数,每个 main 函数都有一个 argv 参数,这个参数是一个字符串数组,这个数组的值是由该 C 程序的父进程在通过 exec* 函数启动它时指定的. 很多人说 ...
- CSS样式自动换行(强制换行)与强制不换行
自动换行问题,正常字符的换行是比较合理的,而连续的数字和英文字符常常将容器撑大,挺让人头疼,下面介绍的是CSS如何实现换行的方法 对于div,p等块级元素,正常文字的换行(亚洲文字和非亚洲文字)元素拥 ...
- Python全栈开发【基础二】
Python全栈开发[基础二] 本节内容: Python 运算符(算术运算.比较运算.赋值运算.逻辑运算.成员运算) 基本数据类型(数字.布尔值.字符串.列表.元组.字典) 其他(编码,range,f ...