poj 3294 Life Forms - 后缀数组 - 二分答案
用奇怪的字符把它们连接起来。然后求sa,hei,二分答案,按mid分组。
判断每一组存在的后缀属于的原串的种类数是不是存在那么多个。
这个做法可以推广到多串求LCS,然后多个log,完美在SPOJ上T掉。
Code
/**
* poj
* Problem#3294
* Accepted
* Time: 391ms
* Memory: 5024k
*/
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#ifndef WIN32
#define Auto "%lld"
#else
#define Auto "%I64d"
#endif
using namespace std;
typedef bool boolean;
#define ll long long #define pii pair<int, int>
#define fi first
#define sc second const int N = 1e5 + , M = ; typedef class Pair3 {
public:
int x, y, id; Pair3() { }
Pair3(int x, int y, int id):x(x), y(y), id(id) { }
}Pair3; typedef class SuffixArray {
protected:
Pair3 T1[N], T2[N];
int cnt[N]; public:
int n;
char *str;
int sa[N], rk[N], hei[N]; void set(int n, char* str) {
this->n = n;
this->str = str;
memset(sa, , sizeof(sa));
memset(rk, , sizeof(rk));
memset(hei, , sizeof(hei));
} void radix_sort(Pair3* x, Pair3* y) {
int m = max(n, );
memset(cnt, , sizeof(int) * m);
for (int i = ; i < n; i++)
cnt[x[i].y]++;
for (int i = ; i < m; i++)
cnt[i] += cnt[i - ];
for (int i = ; i < n; i++)
y[--cnt[x[i].y]] = x[i]; memset(cnt, , sizeof(int) * m);
for (int i = ; i < n; i++)
cnt[y[i].x]++;
for (int i = ; i < m; i++)
cnt[i] += cnt[i - ];
for (int i = n - ; ~i; i--)
x[--cnt[y[i].x]] = y[i];
} void build() {
for (int i = ; i < n; i++)
rk[i] = str[i];
for (int k = ; k < n; k <<= ) {
for (int i = ; i + k < n; i++)
T1[i] = Pair3(rk[i], rk[i + k], i);
for (int i = n - k; i < n; i++)
T1[i] = Pair3(rk[i], , i);
radix_sort(T1, T2);
int diff = ;
rk[T1[].id] = ;
for (int i = ; i < n; i++)
rk[T1[i].id] = (T1[i].x == T1[i - ].x && T1[i].y == T1[i - ].y) ? (diff) : (++diff);
if (diff == n - )
break;
}
for (int i = ; i < n; i++)
sa[rk[i]] = i;
} void get_height() {
for (int i = , j, k = ; i < n; i++, (k) ? (k--) : ()) {
if (rk[i]) {
j = sa[rk[i] - ];
while (i + k < n && j + k < n && str[i + k] == str[j + k]) k++;
hei[rk[i]] = k;
}
}
} const int& operator [] (int p) {
return sa[p];
} const int& operator () (int p) {
return hei[p];
}
}SuffixArray; int n, m, K;
char S[N];
int suf[N];
SuffixArray sa; inline boolean init() {
scanf("%d", &m);
if (!m)
return false;
K = (m >> ) + ;
scanf("%s", S);
n = strlen(S);
for (int i = ; i < m; i++) {
S[n++] = '?';
scanf("%s", S + n);
n += strlen(S + n);
}
suf[n] = ;
for (int i = n - ; ~i; i--)
suf[i] = suf[i + ] + (S[i] == '?');
sa.set(n, S);
return true;
} int chk_clock = ;
int vis[M]; boolean check(int L, int R, int mid) { // [L, R)
if (R - L < K)
return false;
if (suf[sa[L]] - suf[sa[L] + mid])
return false;
chk_clock++;
int rt = ;
for (int i = L; i < R && rt < K; i++)
if (vis[suf[sa[i]]] != chk_clock)
vis[suf[sa[i]]] = chk_clock, rt++;
return rt >= K;
} boolean check(int mid) {
int lst = ;
boolean rt = false;
for (int i = ; i < n && !rt; i++)
if (sa(i) < mid)
rt |= check(lst, i, mid), lst = i;
if (!rt)
rt |= check(lst, n, mid);
return rt;
} void output(int L, int R, int res) {
if (!check(L, R, res))
return;
for (int i = sa[L], j = ; j < res; j++)
putchar(S[i + j]);
putchar('\n');
} inline void solve() {
chk_clock = ;
memset(vis, , sizeof(vis)); sa.build();
sa.get_height(); int l = , r = n / m, mid;
while (l <= r) {
mid = (l + r) >> ;
if (check(mid))
l = mid + ;
else
r = mid - ;
} if (!(--l))
puts("?");
else {
int lst = ;
for (int i = ; i < n; i++)
if (sa(i) < l)
output(lst, i, l), lst = i;
output(lst, n, l);
}
puts("");
} int main() {
while (init())
solve();
return ;
}
poj 3294 Life Forms - 后缀数组 - 二分答案的更多相关文章
- Poj 3294 Life Forms (后缀数组 + 二分 + Hash)
		
题目链接: Poj 3294 Life Forms 题目描述: 有n个文本串,问在一半以上的文本串出现过的最长连续子串? 解题思路: 可以把文本串用没有出现过的不同字符连起来,然后求新文本串的heig ...
 - POJ 3294 Life Forms 后缀数组+二分 求至少k个字符串中包含的最长子串
		
Life Forms Description You may have wondered why most extraterrestrial life forms resemble humans, ...
 - Poj 1743 Musical Theme(后缀数组+二分答案)
		
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 28435 Accepted: 9604 Descri ...
 - Poj 3261 Milk Patterns(后缀数组+二分答案)
		
Milk Patterns Case Time Limit: 2000MS Description Farmer John has noticed that the quality of milk g ...
 - POJ3294--Life Forms 后缀数组+二分答案   大于k个字符串的最长公共子串
		
Life Forms Time Limit: 500 ...
 - POJ 1226 Substrings(后缀数组+二分答案)
		
[题目链接] http://poj.org/problem?id=1226 [题目大意] 求在每个给出字符串中出现的最长子串的长度,字符串在出现的时候可以是倒置的. [题解] 我们将每个字符串倒置,用 ...
 - poj 3415 Common Substrings - 后缀数组 - 二分答案 - 单调栈
		
题目传送门 传送点I 传送点II 题目大意 给定串$A, B$,求$A$和$B$长度大于等于$k$的公共子串的数量. 根据常用套路,用一个奇怪的字符把$A$,$B$连接起来,然后二分答案,然后按mid ...
 - BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案
		
BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案 Description 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l 读入单 ...
 - POJ 3294 Life Forms(后缀数组+二分答案)
		
[题目链接] http://poj.org/problem?id=3294 [题目大意] 求出在至少在一半字符串中出现的最长子串. 如果有多个符合的答案,请按照字典序输出. [题解] 将所有的字符串通 ...
 
随机推荐
- I - The lazy programmer  贪心+优先队列
			
来源poj2970 A new web-design studio, called SMART (Simply Masters of ART), employs two people. The fir ...
 - nginx_ssl证书双向认证以及负载均衡配置
			
#user nobody;worker_processes 1; #error_log logs/error.log;#error_log logs/error.log notice;#error_l ...
 - 手把手JDK环境变量配置
			
分为下载,配置,验证三个步骤解释如何进行JDK环境变量配置. 步骤一: 首先查看配置成功后的效果: tip:点击win——>运行(或者使用win+r,或者shift+鼠标右键打开powershe ...
 - vue3版本到vue2版本的桥接工具
			
vue2的命令可以正常使用.
 - string  find_last_of 用法
			
int find_first_of(char c, int start = 0): 查找字符串中第1个出现的c,由位置start开始. 如果有匹配, ...
 - 嵌入式常用技术概览之IIC(I2C)
			
一.先决知识 (1)模电基础知识(用以理解IIC如何通信) 二.IIC概览 I2C是80年代飞利浦(Philips->NXP->高通)研 ...
 - 2018-2019-2 20175320实验一《Java开发环境的熟悉》实验报告
			
2018-2019-2 20175320实验一<Java开发环境的熟悉>实验报告 一.实验步骤及内容 (一)带包程序的编译运行 1.使用mkdir命令创建如图所示目录 2.进入exp1下的 ...
 - [daily] fedora用过光盘做dnf repo
			
有时候上不了网,或者你在一个网络下行受限的鬼地方上班.可是你需要给你的server装一个包. 这个时候,不妨用一下安装盘吧! 如下: 与redhat下用yum的时候,是一样一样的. 步骤如下: 1,插 ...
 - Spring框架源码阅读之Springs-beans(一)容器的基本实现概述(待续)
			
去年通过实际框架代码的阅读,以及结合<Spring源码深度解析>和<Spring技术内幕>的阅读,对Spring框架内Bean模块有了一个整体性的认识.对此进行的总结性整理和回 ...
 - springboot中通过cors协议解决跨域问题
			
1.对于前后端分离的项目来说,如果前端项目与后端项目部署在两个不同的域下,那么势必会引起跨域问题的出现. 针对跨域问题,我们可能第一个想到的解决方案就是jsonp,并且以前处理跨域问题我基本也是这么处 ...