题意:

  给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. netty之粘包分包的处理

    1.netty在进行字节数组传输的时候,会出现粘包和分包的情况.当个数据还好,如果数据量很大.并且不间断的发送给服务器,这个时候就会出现粘包和分包的情况. 2.简单来说:channelBuffer在接 ...

  2. vim程序员加强功能

    1.折叠      1.1折叠的方式有六种           manual:以标准的vim结构定义折叠跨越的范围,类似移动命令           indent:折叠与折叠的层次,对应于文本的缩排与 ...

  3. 怎样从Java转换到Kotlin代码:现在就开始使用Kotlin(KAD 29)

    作者:Antonio Leiva 时间:Jul, 4, 2017 原文链接:https://antonioleiva.com/kotlin-from-java/ Kotlin最神奇特性之一是它能与Ja ...

  4. leetcode-反转链表

      转载至:https://blog.csdn.net/fx677588/article/details/72357389 反转一个单链表.   示例: 输入: 1->2->3->4 ...

  5. JAVA基础学习之路(八)[1]String类的基本特点

    String类的两种定义方式: 直接赋值 通过构造方法赋值 //直接赋值 public class test2 { public static void main(String args[]) { S ...

  6. 用 splice 函数分别实现 push、pop、shift、unshift 的方法

    主要需要注意的是不同方法他们本身返回的值应该是什么,是数组当前的长度,还是取出的元素的值,再在splice函数里面进行相应的return就可以了.具体如下: 用 splice函数实现 push方法 f ...

  7. codeforces 359E Neatness(DFS+构造)

    Simon loves neatness. So before he goes to bed, Simon wants to complete all chores in the house. Sim ...

  8. JavaScript筑基篇(二)->JavaScript数据类型

    说明 介绍JavaScript数据类型 目录 前言 参考来源 前置技术要求 JavaScript的6种数据类型 哪6种数据类型 undefined 类型 null 类型 boolean 类型 numb ...

  9. Python中的Dictionary

    Dictionary的创建 1 字面量 >>>D = {'a': 1, 'b': 2} >>>D {'b': 2, 'a': 1} 2 keyword参数 > ...

  10. 《JavaScript 高级程序设计》总结

    一.JS基本概念 1.命名规则 变量名区分大小写(test和Test是两个不同的变量名),标识符采用驼峰命名格式,即:第一个字母小写,剩下的每个有意义的单词首字母大写: 标识符第一个字符必须是以字母. ...