题意:给你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. CQRS学习——Cqrs补丁,async实验以及实现[其二]

    实验——async什么时候提高吞吐 async是一个语法糖,用来简化异步编程,主要是让异步编程在书写上接近于同步编程.总的来收,在await的时候,相当于附加上了一个.ContinueWith(). ...

  2. java对象数组

    问题描述:     java 对象数组的使用 问题解决: 数组元素可以是任何类型(只要所有元素具有相同的类型) 数组元素可以是基本数据类型 数组元素也可以是类对象,称这样的数组为对象数组.在这种情况下 ...

  3. DevSecOps 实施篇!系列(二)

    想在自己公司建立 DevSecOps 计划?没问题,企业规模无论大小,都可轻松实现.这里有5个基本的 DevSecOps 原则可以帮助你启动.当然,如果你对 DevSecOps 还不太熟悉,不妨先看看 ...

  4. Visual C++ 6.0静态、动态链接库

    1.什么是静态连接库,什么是动态链接库          静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib 中的指令都全部被直接包含在最终生成的 EXE 文件中了 ...

  5. MVC 文件上传和图片剪辑

    http://www.cnblogs.com/hinton/archive/2012/03/01/2375465.html http://gallery.kissyui.com/uploader/1. ...

  6. [模拟]ZOJ3480 Duck Typing

    题意:给了一坨...按题目意思输出就好了... 给一组案例 begin class d class c:d class b:c class a:b def d.m def d.n call a.m e ...

  7. Java中List的排序

    第一种方法,就是list中对象实现Comparable接口,代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 2 ...

  8. Vue.js vui 饿了么Vue2.0的组件库

    http://www.oschina.net/news/78038/vue-js-2-0-3 http://git.oschina.net/durcframework/vui http://eleme ...

  9. editplus的配置文件来支持sql语法高亮【转】

      editplus默认是没有sql语法高亮的,原因是它的内部没有sql.stx的这样一个语法文件 我们自己在 EditPlus 的安装目录下面新建一个文件名为sql.stx,然后打开editplus ...

  10. POJ2993——Help Me with the Game(字符串处理+排序)

    Help Me with the Game DescriptionYour task is to read a picture of a chessboard position and print i ...