题意:

给\(n\)个串,要你求出一个最长子串\(A\),\(A\)在每个字串至少都出现\(2\)次且不覆盖,问\(A\)最长长度是多少

思路:

后缀数组处理完之后,二分这个长度,可以\(O(n)\)验证可行性,注意是“不覆盖”(英文不好看不懂),随便搞一下就好了。

代码:

#include<map>
#include<set>
#include<queue>
#include<cmath>
#include<stack>
#include<ctime>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<sstream>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 2e5 + 10;
const int INF = 0x3f3f3f3f;
const ull seed = 11;
const int MOD = 1e9 + 7;
using namespace std; int str[maxn];
int t1[maxn], t2[maxn], c[maxn];
int sa[maxn];
int rk[maxn];
int height[maxn];
bool cmp(int *r, int a, int b, int l){
return r[a] == r[b] && r[a + l] == r[b + l];
}
void da(int *str, int n, int m){
n++;
int i, j, p, *x = t1, *y = t2;
for(i = 0; i < m; i++) c[i] = 0;
for(i = 0; i < n; i++) c[x[i] = str[i]]++;
for(i = 1; i < m; i++) c[i] += c[i - 1];
for(i = n - 1; i >= 0; i--) sa[--c[x[i]]] = i;
for(j = 1; j <= n; j <<= 1){
p = 0;
for(i = n - j; i < n; i++) y[p++] = i;
for(i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
for(i = 0; i < m; i++) c[i] = 0;
for(i = 0; i < n; i++) c[x[y[i]]]++;
for(i = 1; i < m; i++) c[i] += c[i - 1];
for(i = n - 1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
swap(x, y);
p = 1; x[sa[0]] = 0;
for(i = 1; i < n; i++)
x[sa[i]] = cmp(y, sa[i - 1], sa[i], j)? p - 1 : p++;
if(p >= n) break;
m = p;
}
int k = 0;
n--;
for(i = 0; i <= n; i++) rk[sa[i]] = i;
for(i = 0; i < n; i++){
if(k) k--;
j = sa[rk[i] - 1];
while(str[i + k] == str[j + k]) k++;
height[rk[i]] = k;
}
}
char s[maxn];
int belong[maxn];
int num[15], pre[15];
int tot;
bool judge(int n){
for(int i = 1; i <= n; i++){
if(num[i] < 2) return false;
}
return true;
}
bool check(int len, int cnt, int n){
memset(num, 0, sizeof(num));
memset(pre, -1, sizeof(pre));
for(int i = 2; i <= cnt; i++){
if(height[i] >= len){
if(pre[belong[sa[i - 1]]] == -1){
num[belong[sa[i - 1]]]++;
pre[belong[sa[i - 1]]] = sa[i - 1];
}
else if(abs(pre[belong[sa[i - 1]]] - sa[i - 1]) >= len){
num[belong[sa[i - 1]]]++;
}
if(pre[belong[sa[i]]] == -1){
num[belong[sa[i]]]++;
pre[belong[sa[i]]] = sa[i];
}
else if(abs(pre[belong[sa[i]]] - sa[i]) >= len){
num[belong[sa[i]]]++;
}
}
else{
if(judge(n)) return true;
memset(num, 0, sizeof(num));
memset(pre, -1, sizeof(pre));
}
}
return judge(n);
}
int main(){
int n;
int T;
scanf("%d", &T);
while(T--){
scanf("%d", &n);
int cnt = 0;
for(int i = 1; i <= n; i++){
scanf("%s", s);
int len = strlen(s);
for(int j = 0; j < len; j++){
belong[cnt] = i;
str[cnt++] = s[j];
}
belong[cnt] = -i;
str[cnt++] = i;
}
cnt--;
str[cnt] = 0;
da(str, cnt, 130); int l = 1, r = 10000;
int Max = 0;
while(l <= r){
int m = (l + r) >> 1;
if(check(m, cnt, n)){
Max = m;
l = m + 1;
}
else{
r = m - 1;
}
}
printf("%d\n", Max);
}
return 0;
}

SPOJ PHRASES Relevant Phrases of Annihilation(后缀数组 + 二分)题解的更多相关文章

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

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

  2. SPOJ - PHRASES Relevant Phrases of Annihilation

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

  3. 【SPOJ 220】 PHRASES - Relevant Phrases of Annihilation

    [链接]h在这里写链接 [题意]     给你n(n<=10)个字符串.     每个字符串长度最大为1e4;     问你能不能找到一个子串.     使得这个子串,在每个字符串里面都不想交出 ...

  4. BZOJ 3230: 相似子串( RMQ + 后缀数组 + 二分 )

    二分查找求出k大串, 然后正反做后缀数组, RMQ求LCP, 时间复杂度O(NlogN+logN) -------------------------------------------------- ...

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

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

  6. 【bzoj4310】跳蚤 后缀数组+二分

    题目描述 很久很久以前,森林里住着一群跳蚤.一天,跳蚤国王得到了一个神秘的字符串,它想进行研究. 首先,他会把串分成不超过 k 个子串,然后对于每个子串 S,他会从S的所有子串中选择字典序最大的那一个 ...

  7. BZOJ 1717 [USACO06DEC] Milk Patterns (后缀数组+二分)

    题目大意:求可重叠的相同子串数量至少是K的子串最长长度 洛谷传送门 依然是后缀数组+二分,先用后缀数组处理出height 每次二分出一个长度x,然后去验证,在排序的后缀串集合里,有没有连续数量多于K个 ...

  8. POJ 1743 [USACO5.1] Musical Theme (后缀数组+二分)

    洛谷P2743传送门 题目大意:给你一个序列,求其中最长的一对相似等长子串 一对合法的相似子串被定义为: 1.任意一个子串长度都大于等于5 2.不能有重叠部分 3.其中一个子串可以在全部+/-某个值后 ...

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

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

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

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

随机推荐

  1. LSTM+CRF进行序列标注

    为什么使用LSTM+CRF进行序列标注 直接使用LSTM进行序列标注时只考虑了输入序列的信息,即单词信息,没有考虑输出信息,即标签信息,这样无法对标签信息进行建模,所以在LSTM的基础上引入一个标签转 ...

  2. ClickHouse入门:表引擎-HDFS

    前言插件及服务器版本服务器:ubuntu 16.04Hadoop:2.6ClickHouse:20.9.3.45 文章目录 简介 引擎配置 HDFS表引擎的两种使用形式 引用 简介 ClickHous ...

  3. linux自定义安装位置安装jdk

    注:本文系参考网络内容及本人实践得出 1 下载jdk安装包 下载地址:https://www.oracle.com/java/technologies/javase/javase-jdk8-downl ...

  4. 第一章:起步(python环境搭建)

    Python 环境搭建 学习python的第一步,就是要学习python开发环境的配置,在配置好python开发环境后,你需要再安装一款比较趁手的编辑器,事实上,python解释器本身就可以进行一些编 ...

  5. Cisco发现协议

    CDP Cisco Discovery Protocol: 思科发现协议 是一个提供关于直接相连的交换机.路由器和其它Cisco设备的综合信息的专有工具 CDP 能够发现直接相邻的设备而不管这些设备所 ...

  6. 糊糊的学习笔记--Fiddle抓包

    Fiddle简述 Fiddler是一个http调试代理,它能 够记录所有的你电脑和互联网之间的http通讯,Fiddler 可以也可以让你检查所有的http通讯,设置断点,以及Fiddle 所有的&q ...

  7. Windows Server 2008 R2系统安装

    把系统U盘插到服务器上,然后启动服务器进入BIOS界面选择U盘启动. 根据服务器的不同,进入BIOS界面的按钮也不一样,主流的有F10.F11.F12.F2.ESC.delete等. 在从BIOS启动 ...

  8. SpringIOC的注解应用

    SpringIOC的注解应用 ​ 在之前的项目中,我们都是通过xml文件进行bean或者某些属性的赋值,其实还有另外一种注解的方式,在企业开发中使用的很多,在bean上添加注解,可以快速的将bean注 ...

  9. In Search of an Understandable Consensus Algorithm" (https://raft.github.io/raft.pdf) by Diego Ongaro and John Ousterhout.

    In Search of an Understandable Consensus Algorithm" (https://raft.github.io/raft.pdf) by Diego ...

  10. vscode 刚安装运行cnpm命令报错

    平时的开发工具什么都用,最近手贱把vscode卸载掉了,然而重新安装时,自已以前的什么配置都没了~~~~~~,又开始从头搞起,但是一切安装配置完毕,执行cnpm命令时报错,晕!!!!!! 解决办法:执 ...