题意:给你N个串,求一个串在大于等于N/2的模板串中连续出现。如果有多解按字典序最小输出。

白书模板题。二分答案+合并模板串成一个新串,扫秒新串的height数组。

考查后缀数组+LCP

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; const int maxn = * + ; struct SuffixArray
{
int s[maxn]; // 原始字符数组(最后一个字符应必须是0,而前面的字符必须非0)
int sa[maxn]; // 后缀数组
int rank[maxn]; // 名次数组. rank[0]一定是n-1,即最后一个字符
int height[maxn]; // height数组
int t[maxn], t2[maxn], c[maxn]; // 辅助数组
int n; // 字符个数 void clear()
{
n = ;
memset(sa, , sizeof(sa));
} // m为最大字符值加1。调用之前需设置好s和n
void build_sa(int m)
{
int i, *x = t, *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[]] = ;
for(i = ; i < n; i++)
x[sa[i]] = 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--;
int j = sa[rank[i]-];
while(s[i+k] == s[j+k]) k++;
height[rank[i]] = k;
}
}
}; const int maxc = + ; // 串的个数
const int maxl = + ; // 每个串的长度 SuffixArray sa;
int n;
char word[maxl];
int idx[maxn];
int flag[maxc]; // 子串[L,R) 是否符合要求
bool good(int L, int R)
{
memset(flag, , sizeof(flag));
if(R - L <= n/) return false;
int cnt = ;
for(int i = L; i < R; i++)
{
int x = idx[sa.sa[i]];
if(x != n && !flag[x])
{
flag[x] = ;
cnt++;
}
}
return cnt > n/;
} void print_sub(int L, int R)
{
for(int i = L; i < R; i++)
printf("%c", sa.s[i] - + 'a');
printf("\n");
} bool print_solutions(int len, bool print)
{
int L = ;
for(int R = ; R <= sa.n; R++)
{
if(R == sa.n || sa.height[R] < len) // 新开一段
{
if(good(L, R))
{
if(print) print_sub(sa.sa[L], sa.sa[L] + len);
else
return true;
}
L = R;
}
}
return false;
} void solve(int maxlen)
{
if(!print_solutions(, false))
printf("?\n");
else
{
int L = , R = maxlen, M;
while(L < R)
{
M = L + (R-L+)/;
if(print_solutions(M, false)) L = M;
else R = M-;
}
print_solutions(L, true);
}
} // 给字符串加上一个字符,属于字符串i
void add(int ch, int i)
{
idx[sa.n] = i;
sa.s[sa.n++] = ch;
} int main()
{
int kase = ;
while(scanf("%d", &n) == && n)
{
if(kase++ > ) printf("\n");
int maxlen = ;
sa.clear();
for(int i = ; i < n; i++)
{
scanf("%s", word);
int sz = strlen(word);
maxlen = max(maxlen, sz);
for(int j = ; j < sz; j++)
add(word[j] - 'a' + , i);
add( + i, n); // 结束字符
}
add(, n); if(n == ) printf("%s\n", word);
else
{
sa.build_sa( + n);
sa.build_height();
solve(maxlen);
}
}
return ;
}

uva 11107 Life Forms的更多相关文章

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

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

  2. 后缀数组 UVA 11107 Life Forms

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

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

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

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

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

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

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

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

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

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

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

  8. UVA - 11107:Life Forms

    后缀数组height+二分 #include<cstdio> #include<cstdlib> #include<algorithm> #include<c ...

  9. UVA 11107(Life Forms-后缀数组+二分)

    Problem C: Life Forms You may have wondered why most extraterrestrial life forms resemble humans, di ...

随机推荐

  1. 深入js的面向对象学习篇(封装是一门技术和艺术)——温故知新(二)

    下面全面介绍封装和信息隐藏. 通过将一个方法或属性声明为私用的,可以让对象的实现细节对其它对象保密以降低对象之间的耦合程度,可以保持数据的完整性并对其修改方式加以约束.在代码有许多人参与设计的情况下, ...

  2. (五)乱入之如何使用MNIST数据库

    (五)乱入之如何使用MNIST数据库 今天花了整整一天时间查各种资料,终于搞清楚了怎么使用MNIST数据库.哈哈,MNIST,是不是高端洋气上档次?是不是不知道是什么东东? MNIST是一个据说很出名 ...

  3. Flask, Tornado, GEvent, 以及它们的结合的性能比较

    Flask, Tornado, GEvent, 以及它们的结合的性能比较 英文: http://blog.wensheng.com/2011/10/performance-of-flask-torna ...

  4. [LeetCode]Divide Two Integer

    Divide two integers without using multiplication, division and mod operator. 思考:位运算.AC的时候真的想说一句“尼玛.. ...

  5. thinkphp 定制错误页面

    在前台配置文件里加上: 'TMPL_EXCEPTION_FILE' => '.Public/tpl/error.html',// 异常cuowu页面的模板文件 然后在Public下新建一个tpl ...

  6. live555源码研究(四)------UserAuthenticationDatabase类

    一.UserAuthenticationDatabase类作用 1,用户/密码管理 2,鉴权管理 二.类UserAuthenticationDatabase继承关系图                 ...

  7. MapReduce编程系列 — 3:数据去重

    1.项目名称: 2.程序代码: package com.dedup; import java.io.IOException; import org.apache.hadoop.conf.Configu ...

  8. HDFS的命令行操作

    1.namenode –format:格式化DFS 文件系统 2.secondaryNameNode: 运行DFS的 SecondaryNameNode 进程 hadoop secondaryname ...

  9. 细说javascript 中的 window.open() 参数设置

    今天遇到一个问题,就是要用javascript中的window.open()打开一个新的网页,而且新打开的网页要在原来网页的基础之上,在查了一些资料之后,找到里一下方法:(其中,url 为链接的地址) ...

  10. WinCE设置多国语言支持

    最近项目中需要支持中(简繁)日韩英多种语言,在网上找了很多解决办法,最后发现还是MSDN最好. [c-sharp] view plaincopy [HKEY_LOCAL_MACHINE/SYSTEM/ ...