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 [题目大意] 求出在至少在一半字符串中出现的最长子串. 如果有多个符合的答案,请按照字典序输出. [题解] 将所有的字符串通 ...
随机推荐
- java项目(学习和研究)
java项目就是研究,不断的对项目进行迭代,把产品做的越来越好,就是research. 自己想着做一个java项目把,可以类似牛客网,想好自己的预期产品,在设计的过程中可以不断改进和扩展,在做这个项目 ...
- 【登录异常解决】Ubuntu 输入正确的密码后重新返回到登陆界面
症状 Ubuntu 输入正确的密码后,黑屏一闪,重新返回到登陆界面. 原因一:主目录下的.Xauthority文件拥有者变成了root,从而以用户登陆的时候无法都取.Xauthority文件.说明:X ...
- android不知不觉偷拍他人功能实现(手机关闭依然拍照)【申明:来源于网络】
android不知不觉偷拍他人功能实现(手机关闭依然拍照)[申明:来源于网络] 地址:http://blog.csdn.net/huangxiaoguo1/article/details/536660 ...
- asp.net mvc ef 性能监控调试工具 MiniProfiler
MiniProfiler是一款针对.NET, Ruby, Go and Node.js的性能分析的轻量级程序.可以对一个页面本身,及该页面通过直接引用.Ajax.Iframe形式访问的其它页面进行监控 ...
- stm8 iar开发
1.一份官方库基本是通用的. 2.尽量依托cubex for stm8 依托理由: 1.不同型号,不同后缀的芯片,将会被配置不同的外设.比如stm8s103k3系列可能有的是串口1,但是stm8s10 ...
- torch.nn.Embedding
自然语言中的常用的构建词向量方法,将id化后的语料库,映射到低维稠密的向量空间中,pytorch 中的使用如下: import torch import torch.utils.data as Dat ...
- mimikaz常用命令
常用命令,留着自己使用的时候方便查找 mimikatz是一款功能强大的轻量级调试神器,通过它你可以提升进程权限注入进程读取进程内存,当然他最大的亮点也是让阿刚最感兴趣的就是他可以直接从 lsass中获 ...
- shell编程之awk命令详解
shell编程之awk命令详解 a:focus { outline: thin dotted #333; outline: 5px auto -webkit-focus-ring-color; out ...
- 自动重置Language level 5 与 Java Complier 1.5
Intellij IDEA用Maven来构建项目,若pom.xml没有指定版本,总是默认Language level 5 与 Java Compiler 1.5. 以下是两种修改方式: 1. 手动进行 ...
- Golang--选择、循环语法总结
1.判断语句if 条件表达式没有括号 支持初始化表达式 初始化语句的变量自在本block内有效 if a,b,c := 1,2,3;a+b+c>6 { fmt.Println("hah ...