UVA11107 Life Forms --- 后缀数组
UVA11107 Life Forms
题目描述:
求出出现在一半以上的字符串内的最长字符串。
数据范围:
\(\sum len(string) <= 10^{5}\)
非常坑的题目。
思路非常好想。
构造出后缀数组。
二分出\(len\)后用\(height\)分组
记\(bel(i)\)表示排名为\(i\)后缀属于哪一个串
当同一组内的不同的\(bel(i)\)出现了\(n/2\)时,本组内有一组解。
注意:
每行数据间要打一个空行
#include <cstdio>
#include <cstring>
#include <iostream>
#define sid 200050
#define ri register int
using namespace std; template <typename re>
inline void upmax(re &a, re b) { if(a < b) a = b; } int Tt, n, ml, ned;
char s[sid];
int bel[sid], sc[sid];
int flag[];
int sa[sid], rk[sid], cnt[sid], p1[sid], p2[sid], ht[sid]; inline void Suffix() {
int m = ;
int *t1 = p1, *t2 = p2;
for(ri i = ; i <= n; i ++) sc[i] = (s[i] == ) ? ++ m : s[i];
for(ri i = ; i <= n; i ++) t1[i] = sc[i];
for(ri i = ; i <= m; i ++) cnt[i] = ;
for(ri i = ; i <= n; i ++) cnt[t1[i]] ++;
for(ri i = ; i <= m; i ++) cnt[i] += cnt[i - ];
for(ri i = n; i >= ; i --) sa[cnt[t1[i]] --] = i;
for(ri k = ; k <= n; k <<= ) {
int p = ;
for(ri i = ; i <= m; i ++) t2[i] = ;
for(ri i = n - k + ; i <= n; i ++) t2[++ p] = i;
for(ri i = ; i <= n; i ++) if(sa[i] > k) t2[++ p] = sa[i] - k;
for(ri i = ; i <= m; i ++) cnt[i] = ;
for(ri i = ; i <= n; i ++) cnt[t1[t2[i]]] ++;
for(ri i = ; i <= m; i ++) cnt[i] += cnt[i - ];
for(ri i = n; i >= ; i --) sa[cnt[t1[t2[i]]] --] = t2[i];
swap(t1, t2); t1[sa[]] = p = ;
for(ri i = ; i <= n; i ++)
t1[sa[i]] = (t2[sa[i]] == t2[sa[i - ]] && t2[sa[i] + k] == t2[sa[i - ] + k]) ? p : ++ p;
m = p; if(p >= n) break;
}
for(ri i = ; i <= n; i ++) rk[sa[i]] = i;
ri k = , j;
for(ri i = ; i <= n; i ++) {
if(k) k --;
j = sa[rk[i] - ];
while(sc[j + k] == sc[i + k]) k ++;
ht[rk[i]] = k;
}
} inline bool Check(int htk) {
int cnt = , tim = ;
memset(flag, , sizeof(flag));
for(ri i = ; i <= n; i ++) {
if(ht[i] < htk) cnt = , ++ tim;
if(flag[bel[sa[i]]] != tim && bel[sa[i]]) cnt ++, flag[bel[sa[i]]] = tim;
if(cnt >= ned) return ;
}
return ;
} inline int Binary() {
int l = , r = ml, ans = -;
while(l <= r) {
int mid = (l + r) >> ;
if(Check(mid)) l = mid + , ans = mid;
else r = mid - ;
}
return ans;
} inline void Get_Ans(int op) {
if(op == -) {
printf("?\n");
return;
}
memset(flag, , sizeof(flag));
int cnt = , tim = , fag;
for(ri i = ; i <= n; i ++) {
if(ht[i] < op) fag = , cnt = , ++ tim;
if(flag[bel[sa[i]]] != tim && bel[sa[i]]) cnt ++, flag[bel[sa[i]]] = tim;
if(cnt >= ned && !fag) {
int k = sa[i];
for(ri j = ; j <= op; j ++) printf("%c", s[k + j - ]);
printf("\n");
cnt = ; fag = ;
}
}
} int main() {
bool pe = ;
while(scanf("%d", &Tt) == && Tt) {
if(pe) printf("\n"); pe = ;
n = ml = ; ned = Tt / + ;
memset(s, , sizeof(s));
memset(bel, , sizeof(bel));
for(ri i = ; i <= Tt; i ++) {
scanf("%s", s + + n);
int nl = strlen(s + + n);
for(ri j = n + ; j <= n + nl; j ++) bel[j] = i;
upmax(ml, nl); n += nl; s[++ n] = ;
}
if(Tt != ) {
Suffix();
int ans = Binary();
Get_Ans(ans);
}
else {
for(ri j = ; j <= n - ; j ++) printf("%c", s[j]);
printf("\n");
}
}
return ;
}
打开有惊喜
UVA11107 Life Forms --- 后缀数组的更多相关文章
- POJ3294 Life Forms —— 后缀数组 最长公共子串
题目链接:https://vjudge.net/problem/POJ-3294 Life Forms Time Limit: 5000MS Memory Limit: 65536K Total ...
- Poj 3294 Life Forms (后缀数组 + 二分 + Hash)
题目链接: Poj 3294 Life Forms 题目描述: 有n个文本串,问在一半以上的文本串出现过的最长连续子串? 解题思路: 可以把文本串用没有出现过的不同字符连起来,然后求新文本串的heig ...
- POJ3294 Life Forms(后缀数组)
引用罗穗骞论文中的话: 将n 个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开,求后缀数组.然后二分答案,用和例3 同样的方法将后缀分成若干组,判断每组的后缀是否出现在不小于k 个的原串中 ...
- POJ 3294 UVA 11107 Life Forms 后缀数组
相同的题目,输出格式有区别. 给定n个字符串,求最长的子串,使得它同时出现在一半以上的串中. 不熟悉后缀数组的童鞋建议先去看一看如何用后缀数组计算两个字符串的最长公共子串 Ural1517 这道题的思 ...
- POJ3294--Life Forms 后缀数组+二分答案 大于k个字符串的最长公共子串
Life Forms Time Limit: 500 ...
- 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,二分答案,按 ...
- 【UVA11107 训练指南】Life Forms【后缀数组】
题意 输入n(n<=100)个字符串,每个字符串长度<=1000,你的任务是找出一个最长的字符串使得超过一半的字符串都包含这个字符串. 分析 训练指南上后缀数组的一道例题,据说很经典(估计 ...
- 后缀数组LCP + 二分 - UVa 11107 Life Forms
Life Forms Problem's Link Mean: 给你n个串,让你找出出现次数大于n/2的最长公共子串.如果有多个,按字典序排列输出. analyse: 经典题. 直接二分判断答案. 判 ...
随机推荐
- LintCode之硬币排成线
输入的n可以分为两种情况: 1. 如果n是3的倍数的话,不论A怎么拿B都可以拿(3-A拿的个数)来使其保持是3的倍数,他就一定能拿到最后一块,所以n是3的倍数的话B必胜 2. 如果n不是3的倍数的话, ...
- Django之ModelForm(二)-----ModelForm组件
a. class Meta: model, # 对应Model的 fields=None, ...
- 数据类型的判断 --Object.prototype.toString.call(obj)精准检测对象类型
数据类型的判断 typeof typeof返回一个表示数据类型的字符串,返回结果包括:number.boolean.string.symbol.object.undefined.function等7种 ...
- 解决Chrome下表单自动填充后背景色为黄色
Chrome浏览器在表单自动填充后会显示黄色背景,这是Chrome的私有属性导致,对于有洁癖的人来讲,是不喜欢的,我们可以手动去掉. 代码如下: input:-webkit-autofill { -w ...
- CSS 中 nth-child 和 nth-of-type 的区别
假设有如下代码结构,想要查找 Piggy 那个 p <section> <h1>Words</h1> <p>Little</p> <p ...
- Coursera在线学习---第六节.构建机器学习系统
备: High bias(高偏差) 模型会欠拟合 High variance(高方差) 模型会过拟合 正则化参数λ过大造成高偏差,λ过小造成高方差 一.利用训练好的模型做数据预测时,如果效果不好 ...
- EasyUi组合条件分页查询
1.引入css与js文件 <link rel="stylesheet" type="text/css" href="themes/default ...
- Deep Learning基础--各个损失函数的总结与比较
损失函数(loss function)是用来估量你模型的预测值f(x)与真实值Y的不一致程度,它是一个非负实值函数,通常使用L(Y, f(x))来表示,损失函数越小,模型的鲁棒性就越好.损失函数是经验 ...
- linux动态库编译和使用详细剖析 - 后续
引言 - 也许是修行 很久以前写过关于动态库科普文章, 废话反正是说了好多. 核心就是在 linux 上面玩了一下 dlopen : ) linux动态库编译和使用详细剖析 - https://www ...
- [ python ] 练习作业 - 3
1. 写出Python查找一个变量的顺序 提示:4中作用域的顺序 本地作用域(local) --> 当前作用域被嵌入的本地作用域(enclsing locals) --> 全局/模块作用域 ...