题意:

  给n个字符串,求出最长的子串。使得子串在每个字符串中不重叠地至少出现2次。输出子串长度。

题解:

  用后缀数组求出height数组,之后二分答案。check时对height数组进行分组,并维护每个字符串的最前和最后位置。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+;
int t, n, k, len;
int vis[N], val[][];
char s[N];
int r[N];
int sa[N], t1[N], t2[N], c[N], height[N], rank[N];
void SA(int *r, int n, int m) {
int *x = t1, *y = t2;
for(int i = ; i < m; i++) c[i] = ;
for(int i = ; i < n; i++) c[x[i] = r[i]]++;
for(int i = ; i < m; i++) c[i] += c[i-];
for(int i = n-; i >= ; i--) sa[--c[x[i]]] = i;
for(int k = ; k <= n; k <<= ) {
int p = ;
for(int i = n-k; i < n; i++) y[p++] = i;
for(int i = ; i < n; i++) if(sa[i] >= k) y[p++] = sa[i]-k;
for(int i = ; i < m; i++) c[i] = ;
for(int i = ; i < n; i++) c[x[y[i]]]++;
for(int i = ; i < m; i++) c[i] += c[i-];
for(int i = n-; i >= ; i--) sa[--c[x[y[i]]]] = y[i];
swap(x, y);
p = ; x[sa[]] = ;
for(int i = ; i < n; i++)
x[sa[i]] = y[sa[i-]] == y[sa[i]] && y[sa[i-]+k] == y[sa[i]+k] ? p- : p++;
if(p >= n) break;
m = p;
}
int k = , j;
for(int i = ; i < n; i++) rank[sa[i]] = i;
for(int i = ; i < n; height[rank[i++]] = k)
for(k ? k--:, j = sa[rank[i]-]; r[i+k] == r[j+k]; k++);
}
int add(int x, int v) {
int p = vis[sa[x]], c = ;
if(val[p][] == - && val[p][] == -) {
val[p][] = val[p][] = sa[x];
c++;
}
else {
if(sa[x] < val[p][]) {
if(val[p][] - val[p][] < v && val[p][] - sa[x] >= v) c++;
val[p][] = sa[x];
}
else if(sa[x] > val[p][]) {
if(val[p][] - val[p][] < v && sa[x] - val[p][] >= v) c++;
val[p][] = sa[x];
}
}
return c;
}
bool check(int x) {
int cnt = ;
int l = n;
while(l < len) {
if(height[l] < x) {
memset(val, -, sizeof(val));
cnt = ;
cnt += add(l, x);
}
else cnt += add(l, x);
l++;
if(cnt == *n) return true;
}
return false;
}
int main() {
scanf("%d", &t);
while(t--) {
len = ;
scanf("%d", &n);
memset(vis, , sizeof(vis));
for(int i = ; i <= n; i++) {
scanf("%s", s);
k = strlen(s);
for(int j = ; j < k; j++) r[len++] = s[j]-'a'+;
vis[len] = ;
r[len++] = i;
}
for(int i = ; i < len; i++) vis[i] += vis[i-];
SA(r, len, );
int l = , r = 1e5;
while(l <= r) {
int mid = l+r>>;
if(check(mid)) l = mid+;
else r = mid-;
}
printf("%d\n", r);
}
}

SPOJ - PHRASES的更多相关文章

  1. SPOJ PHRASES 每个字符串至少出现两次且不重叠的最长子串

    Description You are the King of Byteland. Your agents have just intercepted a batch of encrypted ene ...

  2. POJ - 3294~Relevant Phrases of Annihilation SPOJ - PHRASES~Substrings POJ - 1226~POJ - 3450 ~ POJ - 3080 (后缀数组求解多个串的公共字串问题)

    多个字符串的相关问题 这类问题的一个常用做法是,先将所有的字符串连接起来, 然后求后缀数组 和 height 数组,再利用 height 数组进行求解. 这中间可能需要二分答案. POJ - 3294 ...

  3. SPOJ - PHRASES Relevant Phrases of Annihilation

    传送门:SPOJ - PHRASES(后缀数组+二分) 题意:给你n个字符串,找出一个最长的子串,他必须在每次字符串中都出现至少两次. 题解:被自己蠢哭...记录一下自己憨憨的操作,还一度质疑评测鸡( ...

  4. SPOJ PHRASES 后缀数组

    题目链接:http://www.spoj.com/problems/PHRASES/en/ 题意:给定n个字符串,求一个最长的子串至少在每个串中的不重叠出现次数都不小于2.输出满足条件的最长子串长度 ...

  5. SPOJ - PHRASES K - Relevant Phrases of Annihilation

    K - Relevant Phrases of Annihilation 题目大意:给你 n 个串,问你最长的在每个字符串中出现两次且不重叠的子串的长度. 思路:二分长度,然后将height分块,看是 ...

  6. SPOJ - PHRASES Relevant Phrases of Annihilation —— 后缀数组 出现于所有字符串中两次且不重叠的最长公共子串

    题目链接:https://vjudge.net/problem/SPOJ-PHRASES PHRASES - Relevant Phrases of Annihilation no tags  You ...

  7. SPOJ - PHRASES Relevant Phrases of Annihilation (后缀数组)

    You are the King of Byteland. Your agents have just intercepted a batch of encrypted enemy messages ...

  8. SPOJ PHRASES Relevant Phrases of Annihilation(后缀数组 + 二分)题解

    题意: 给\(n\)个串,要你求出一个最长子串\(A\),\(A\)在每个字串至少都出现\(2\)次且不覆盖,问\(A\)最长长度是多少 思路: 后缀数组处理完之后,二分这个长度,可以\(O(n)\) ...

  9. KUANGBIN带你飞

    KUANGBIN带你飞 全专题整理 https://www.cnblogs.com/slzk/articles/7402292.html 专题一 简单搜索 POJ 1321 棋盘问题    //201 ...

随机推荐

  1. 征战 OSG-序及目录

    其实很早就应该写这个了,一直拖到现在就是因为懒啊. 自从七月演习回来,被划到三维平台开发部,就一直混日子,也没人带领,也没人问结果,就这么一直堕落下来了,直到有一天才发现自己也看不上自己了,觉得自己这 ...

  2. 怎样安装Appium

    在浏览器地址栏输入 http://appium.io/ 打开Appium官网: 安装包下载完成后, 一路默认安装, 什么都不用点击, 等待大约10分钟: 安装完成后, 会在桌面生成快捷图标: 启动: ...

  3. Python 的非正式介绍

    在下面的例子中,通过提示符 (>>> 与 ...) 的出现与否来区分输入和输出:如果你想复现这些例子,当提示符出现后,你必须在提示符后键入例子中的每一个词:不以提示符开头的那些行是解 ...

  4. [CodeForce431C]k-tree

    Quite recently a creative student Lesha had a lecture on trees. After the lecture Lesha was inspired ...

  5. python学习笔记04 --------------基本运算符

    1.算数运算 + 加 - 减 * 乘 /   除 % 取模(先做除法,然后返回余数) ** 乘方(幂运算) //          取整(相除,然后返回商的整数部分) 2.比较运算(返回布尔值) == ...

  6. Java基础知识:Java实现Map集合二级联动1

    Java实现Map集合二级联动 Map集合可以保存键值映射关系,这非常适合本实例所需要的数据结构,所有省份信息可以保存为Map集合的键,而每个键可以保存对应的城市信息,本实例就是利用Map集合实现了省 ...

  7. 1.EOS源码编译运行

    目前网络上都是针对老版EOS2.0源码编译的文章,我在mac上参考这些文章编译,最后发现根本就不对,最新版本只需一条命令(./eosio_build.sh,依赖库会自动安装的)即可.我根据这些文章手动 ...

  8. Kali信息收集-DNS

    1.whois查询 直接在终端输入whois 域名 2.查找dns服务器 (1)host (2)dig (3)nslookup 3.域传输 4.域名枚举 (1)dnsdict6 kali没有集成这款工 ...

  9. POJ 3028 Shoot-out(概率DP)

    Description This is back in the Wild West where everybody is fighting everybody. In particular, ther ...

  10. php分页类的实现与调用 (自我摘记)

    page.class.php <?php namespace Component; class Page { private $total; //数据表中总记录数 private $listRo ...