题目传送门

  传送门I

  传送门II

题目大意

  给定$n$个串,询问所有出现在严格大于$\frac{n}{2}$个串的最长串。不存在输出'?'

  用奇怪的字符把它们连接起来。然后求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 - 后缀数组 - 二分答案的更多相关文章

  1. Poj 3294 Life Forms (后缀数组 + 二分 + Hash)

    题目链接: Poj 3294 Life Forms 题目描述: 有n个文本串,问在一半以上的文本串出现过的最长连续子串? 解题思路: 可以把文本串用没有出现过的不同字符连起来,然后求新文本串的heig ...

  2. POJ 3294 Life Forms 后缀数组+二分 求至少k个字符串中包含的最长子串

    Life Forms   Description You may have wondered why most extraterrestrial life forms resemble humans, ...

  3. Poj 1743 Musical Theme(后缀数组+二分答案)

    Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 28435 Accepted: 9604 Descri ...

  4. Poj 3261 Milk Patterns(后缀数组+二分答案)

    Milk Patterns Case Time Limit: 2000MS Description Farmer John has noticed that the quality of milk g ...

  5. POJ3294--Life Forms 后缀数组+二分答案 大于k个字符串的最长公共子串

                                                                              Life Forms Time Limit: 500 ...

  6. POJ 1226 Substrings(后缀数组+二分答案)

    [题目链接] http://poj.org/problem?id=1226 [题目大意] 求在每个给出字符串中出现的最长子串的长度,字符串在出现的时候可以是倒置的. [题解] 我们将每个字符串倒置,用 ...

  7. poj 3415 Common Substrings - 后缀数组 - 二分答案 - 单调栈

    题目传送门 传送点I 传送点II 题目大意 给定串$A, B$,求$A$和$B$长度大于等于$k$的公共子串的数量. 根据常用套路,用一个奇怪的字符把$A$,$B$连接起来,然后二分答案,然后按mid ...

  8. BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案

    BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案 Description          给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l        读入单 ...

  9. POJ 3294 Life Forms(后缀数组+二分答案)

    [题目链接] http://poj.org/problem?id=3294 [题目大意] 求出在至少在一半字符串中出现的最长子串. 如果有多个符合的答案,请按照字典序输出. [题解] 将所有的字符串通 ...

随机推荐

  1. Grunt jshint Warning: Path must be a string . Received null Use

    用grunt监视文件,出现'Warning: Path must be a string . Received null Use --force to continue 原因是没有设置reporter ...

  2. 防止vue文件中的样式出现‘污染’情况(html5 scoped特性)

    近期在项目中出现了vue样式污染的情况: 一个页面刚进去时样式不正常,刷新之后,样式才才达到预期那样 在vue中,如果把样式写在vue文件的 style中,可能会出现样式污染的情况,这是要把写样式的标 ...

  3. 27、 jq 拖拽

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  4. swust oj 962

    括号匹配问题 1000(ms) 65535(kb) 3045 / 13375 假设表达式中允许包含两种括号:圆括号和方括号.编写一个算法判断表达式中的括号是否正确配对. 输入 由括号构成的字符串,包含 ...

  5. git版本控制工具

    git 基本操作 1.git init 在一个文件夹下执行该命令,对该文件夹下的内容进行管理.在该文件夹下会创建一个隐藏的目录.git 2.git status 查看文件夹下内容的状态,没有更改的则什 ...

  6. odoo二次开发 tips

    1.model属性 每个对象(即class)一般由字段(变量)和函数组成,每个对象对应着数据库中的一张表,驼峰命名方式 models.Model 基础模块,会根据字段和模型名在后台数据库生成对应得表文 ...

  7. Grafana 安装及 Windows 应用程序服务配置工具 NSSM使用

    网址:https://blog.csdn.net/kk185800961/article/details/83515382 1.进入conf文件,将 defaults.ini 复制一份,命名为cust ...

  8. 格式化输出&初始编码&运算符

    一:格式化输出 %     %d   %s %为占位符   S替换的内容的类型为字符型 d替换的内容为整型 若在格式化输出的时候需要正常用到% 则表示时用两个%%表示 如: name = input( ...

  9. -webkit-line-clamp、-webkit-box-orient vue 打包部署后不起作用??

    场景分析:实际开发中,文字描述过长,需要两行或三行显示缩略显示: 实现过程: 实现过程遇到的问题:打包到线上后发现并没有-webkit-box-orient属性,导致省略号并没有按预期展示: 解决方法 ...

  10. VUE—打印(原生态网页打印)

    //打印触发的方法 print(e){ let subOutputRankPrin = document.getElementById('printcode'); var options = { fo ...