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: 经典题. 直接二分判断答案. 判 ...
随机推荐
- 面向对象 ( OO ) 的程序设计——继承
本文地址:http://www.cnblogs.com/veinyin/p/7608282.html 仅支持实现继承,且主要依靠原型链来实现,不过一般会混合构造函数一起实现继承 1 原型链 继承使用 ...
- 查询PHP版本
查询php版本: phpinfo();
- JS跳转页面常用的几种方法
第0种:(常用) function triggerAOnclick(){ window.open("http://localhost/jwxt/forward/2TrainSchemeDat ...
- redhat5.5 x64 安装oracle 11g
http://www.cnblogs.com/jamesf/p/4769086.html http://blog.csdn.net/yakson/article/details/9012129
- Linux内核中的常用宏container_of其实很简单【转】
转自:http://blog.csdn.net/npy_lp/article/details/7010752 开发平台:Ubuntu11.04 编 译器:gcc version 4.5.2 (Ubun ...
- ahttp
# -*- coding: utf-8 -*- # @Time : 2018/8/20 14:35 # @Author : cxa # @File : chttp.py # @Software: Py ...
- 进程一些命令pstree,ps,pstack,top
1. pstree pstree以树结构显示进程$ pstree -p work | grep adsshd(22669)---bash(22670)---ad_preprocess(4551)-+- ...
- scrapy抓取小说
用scrapy建立一个project,名字为Spider scrapy startproject Spider 因为之前一直用的是电脑自带的python版本,所以在安装scrapy时,有很多问题,也没 ...
- explicit浅谈
在C++中,explicit关键字主要用于防止隐式转换,用于修饰构造函数.复制构造函数. 例如有一个类: class A { public: A( int count ) : m_data( coun ...
- WordPress插件:WP No Category Base 去除分类Category目录
不少折腾WordPress的朋友都希望去掉分类链接中的 /category/ 目录标志,网上很多这方面的教程,据倡萌所知,除了使用 WP No Category Base 插件(或类似插件),其他的方 ...