后缀数组height+二分

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<iostream>
#define MAXN 100*10000+10
#define pii pair<int,int>
using namespace std;
struct Node{
pii v;
int p;
friend bool operator < (const Node &p1,const Node &p2){
return (p1.v<p2.v);
}
}tsa[MAXN]; char s[MAXN];
int T,n;
int b[],p[MAXN],ans[MAXN];
int rk[MAXN],sa[MAXN];
void build_sa(){
for(int i=;i<=n;i++){
rk[i]=s[i]-;
}
for(int k=;k<=n;k<<=){
for(int i=;i<=n-k;i++){
tsa[i].v=make_pair(rk[i],rk[i+k]);
tsa[i].p=i;
}
for(int i=n-k+;i<=n;i++){
tsa[i].v=make_pair(rk[i],);
tsa[i].p=i;
}
sort(tsa+,tsa+n+);
int cnt=;
for(int i=;i<=n;i++){
if(!cnt||tsa[i].v!=tsa[i-].v){
cnt++;
}
rk[tsa[i].p]=cnt;
}
if(cnt>=n)break;
}
for(int i=;i<=n;i++){
sa[rk[i]]=i;
}
}
int height[MAXN];
void build_height(){
int k=;
for(int i=;i<=n;i++){
if(k)k--;
int j=sa[rk[i]-];
while(s[i+k]==s[j+k]){
k++;
}
height[rk[i]]=k;
}
}
void init(){
n=;
char tmp='z'+;
for(int i=;i<=T;i++){
scanf("%s",s+n+);
int t=n;
n=strlen(s+);
s[++n]=(tmp++);
for(int j=t+;j<=n;j++){
p[j]=i;
}
}
build_sa();
build_height();
}
int check(int x){
memset(b,,sizeof(b));
int cnt=;
int ret=;
for(int i=;i<=n;i++){
if(height[i]>=x){
if(!cnt){
if(p[sa[i]]==p[sa[i-]]){
cnt=;
}
else{
cnt=;
}
b[p[sa[i]]]=b[p[sa[i-]]]=;
}
else if(!b[p[sa[i]]]){
b[p[sa[i]]]=;
cnt++;
}
if(cnt>T/){
ans[sa[i]]=;
ret=;
}
}
else{
memset(b,,sizeof(b));
cnt=;
}
}
return ret;
}
vector<string> vs;
string ept;
void print(int x){
vs.clear();
string ts(s,n+);
for(int i=;i<=n;i++){
if(ans[i]){
string t;
t=ept;
for(int j=i;j<=i+x-;j++){
t+=s[j];
}
vs.push_back(t);
}
}
sort(vs.begin(),vs.end());
vs.erase(unique(vs.begin(),vs.end()),vs.end());
for(int i=;i<vs.size();i++){
cout<<vs[i]<<endl;
}
}
void solve(){
// for(int i=1;i<=n;i++){
// for(int j=sa[i];j<=n;j++){
// printf("%c",s[j]);
// }
// printf("\n");
// }
// for(int i=6;i<=n;i++){
// printf("%d\n",check(i));
// }
int L=,R=n;
while(R-L>){
int mid=(L+R)/;
if(check(mid)){
L=mid;
}
else{
R=mid;
}
}
memset(ans,,sizeof(ans));
if(R&&check(R)){
print(R);
}
else{
if(L&&check(L)){
print(L);
}
else{
printf("?\n");
}
}
}
int main()
{
// freopen("data.in","r",stdin);
// freopen("my.out","w",stdout);
int flag=;
while(){
scanf("%d",&T);
if(!T)break;
if(flag){
printf("\n");
}
else{
flag=;
}
if(T==){
scanf("%s",s+);
printf("%s\n",s+);
continue;
}
init();
solve();
}
return ;
}

UVA - 11107:Life Forms的更多相关文章

  1. 后缀数组练习4:Life Forms

    有一个细节不是特别懂,然后的话细节有点多,就是挺难发现的那一种,感谢大佬的博客 1470: 后缀数组4:Life Forms poj3294 时间限制: 1 Sec  内存限制: 128 MB提交: ...

  2. 后缀数组 UVA 11107 Life Forms

    题目链接 题意:训练指南P223 分析:二分长度,把所有字符串连成一个字符串,中间用不同的字符分隔(这是为了保证匹配长度始终在一个字符串内).height数组分段,vis数组标记哪些字符串被访问了,如 ...

  3. UVa 11107 (后缀数组 二分) Life Forms

    利用height值对后缀进行分组的方法很常用,好吧,那就先记下了. 题意: 给出n个字符串,求一个长度最大的字符串使得它在超过一半的字符串中出现. 多解的话,按字典序输出全部解. 分析: 在所有输入的 ...

  4. uva 11107 Life Forms

    题意:给你N个串,求一个串在大于等于N/2的模板串中连续出现.如果有多解按字典序最小输出. 白书模板题.二分答案+合并模板串成一个新串,扫秒新串的height数组. 考查后缀数组+LCP #inclu ...

  5. 后缀数组LCP + 二分 - UVa 11107 Life Forms

    Life Forms Problem's Link Mean: 给你n个串,让你找出出现次数大于n/2的最长公共子串.如果有多个,按字典序排列输出. analyse: 经典题. 直接二分判断答案. 判 ...

  6. UVA - 11107 Life Forms (广义后缀自动机)

    题意:给你n个字符串,求出在超过一半的字符串中出现的所有子串中最长的子串,按字典序输出. 对这n个字符串建广义后缀自动机,建完后每个字符串在自动机上跑一遍,沿fail树向上更新所有子串结点的出现次数( ...

  7. UVA - 11107 Life Forms (广义后缀自动机+后缀树/后缀数组+尺取)

    题意:给你n个字符串,求出在超过一半的字符串中出现的所有子串中最长的子串,按字典序输出. 这道题算是我的一个黑历史了吧,以前我的做法是对这n个字符串建广义后缀自动机,然后在自动机上dfs,交上去AC了 ...

  8. UVA 11107 Life Forms——(多字符串的最长公共子序列,后缀数组+LCP)

    题意: 输入n个序列,求出一个最大长度的字符串,使得它在超过一半的DNA序列中连续出现.如果有多解,按照字典序从小到大输出所有解. 分析:这道题的关键是将多个字符串连接成一个串,方法是用不同的分隔符把 ...

  9. POJ 3294 UVA 11107 Life Forms 后缀数组

    相同的题目,输出格式有区别. 给定n个字符串,求最长的子串,使得它同时出现在一半以上的串中. 不熟悉后缀数组的童鞋建议先去看一看如何用后缀数组计算两个字符串的最长公共子串 Ural1517 这道题的思 ...

随机推荐

  1. Beta阶段敏捷冲刺报告-DAY4

    Beta阶段敏捷冲刺报告-DAY4 Scrum Meeting 敏捷开发日期 2017.11.5 会议时间 11:30 会议地点 羽毛球场 参会人员 全体成员 会议内容 bug的原因讨论, 测试内容安 ...

  2. 操作 numpy 数组的常用函数

    操作 numpy 数组的常用函数 where 使用 where 函数能将索引掩码转换成索引位置: indices = where(mask) indices => (array([11, 12, ...

  3. 教你在不使用框架的情况下也能写出现代化 PHP 代码

    我为你们准备了一个富有挑战性的事情.接下来你们将以 无 框架的方式开启一个项目之旅. 首先声明, 这篇并非又臭又长的反框架裹脚布文章.也不是推销 非原创 思想 .毕竟, 我们还将在接下来的开发之旅中使 ...

  4. c# gridview 新增行

    string[] newRow = {"long","d","b"}; Gridview.Rows.Insert(Gridview.Rows ...

  5. JAVA_SE基础——19.数组的定义

    数组是一组相关数据的集合,数组按照使用可以分为一维数组.二维数组.多维数组 本章先讲一维数组 不同点: 不使用数组定义100个整形变量:int1,int2,int3;;;;;; 使用数组定义 int ...

  6. Linux入门(2)_给初学者的建议

    1 学习Linux的注意事项 严格区分大小写(命令, 文件, 选项) Linux中所有内容以文件形式保存, 包括硬件 硬盘文件是/dev/sd[a-p] 光盘文件是/dev/sr0等 Linux不靠扩 ...

  7. Spring知识点回顾(06)Profile 和 条件注解 @Conditional

    1.设定环境中的active profiles 如:DispatcherServerlet的init-param spring.profiles.active=production spring.pr ...

  8. hadoop2.7.3+spark2.1.0+scala2.12.1环境搭建(4)SPARK 安装

    hadoop2.7.3+spark2.1.0+scala2.12.1环境搭建(4)SPARK 安装 一.依赖文件安装 1.1 JDK 参见博文:http://www.cnblogs.com/liugh ...

  9. pandas.DataFrame.describe 官方文档翻译percentile_width,percentiles,include, exclude

     使用格式:DataFrame.describe(percentile_width=None, percentiles=None, include=None, exclude=None)  作用:生成 ...

  10. 证明二叉查找树所有节点的平均深度为O(logN)

    数据结构与算法分析(c语言描述)第4章 P78 概念一:一棵树所有节点的深度和称为内部路径长 令D(N)为一棵有N节点的树的内部路径长么,即有D(1)=0, 设一棵树的左子树的内部路径长为D(i),则 ...