题意:

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

题解:

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

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N = 1e5+;
  4. int t, n, k, len;
  5. int vis[N], val[][];
  6. char s[N];
  7. int r[N];
  8. int sa[N], t1[N], t2[N], c[N], height[N], rank[N];
  9. void SA(int *r, int n, int m) {
  10. int *x = t1, *y = t2;
  11. for(int i = ; i < m; i++) c[i] = ;
  12. for(int i = ; i < n; i++) c[x[i] = r[i]]++;
  13. for(int i = ; i < m; i++) c[i] += c[i-];
  14. for(int i = n-; i >= ; i--) sa[--c[x[i]]] = i;
  15. for(int k = ; k <= n; k <<= ) {
  16. int p = ;
  17. for(int i = n-k; i < n; i++) y[p++] = i;
  18. for(int i = ; i < n; i++) if(sa[i] >= k) y[p++] = sa[i]-k;
  19. for(int i = ; i < m; i++) c[i] = ;
  20. for(int i = ; i < n; i++) c[x[y[i]]]++;
  21. for(int i = ; i < m; i++) c[i] += c[i-];
  22. for(int i = n-; i >= ; i--) sa[--c[x[y[i]]]] = y[i];
  23. swap(x, y);
  24. p = ; x[sa[]] = ;
  25. for(int i = ; i < n; i++)
  26. x[sa[i]] = y[sa[i-]] == y[sa[i]] && y[sa[i-]+k] == y[sa[i]+k] ? p- : p++;
  27. if(p >= n) break;
  28. m = p;
  29. }
  30. int k = , j;
  31. for(int i = ; i < n; i++) rank[sa[i]] = i;
  32. for(int i = ; i < n; height[rank[i++]] = k)
  33. for(k ? k--:, j = sa[rank[i]-]; r[i+k] == r[j+k]; k++);
  34. }
  35. int add(int x, int v) {
  36. int p = vis[sa[x]], c = ;
  37. if(val[p][] == - && val[p][] == -) {
  38. val[p][] = val[p][] = sa[x];
  39. c++;
  40. }
  41. else {
  42. if(sa[x] < val[p][]) {
  43. if(val[p][] - val[p][] < v && val[p][] - sa[x] >= v) c++;
  44. val[p][] = sa[x];
  45. }
  46. else if(sa[x] > val[p][]) {
  47. if(val[p][] - val[p][] < v && sa[x] - val[p][] >= v) c++;
  48. val[p][] = sa[x];
  49. }
  50. }
  51. return c;
  52. }
  53. bool check(int x) {
  54. int cnt = ;
  55. int l = n;
  56. while(l < len) {
  57. if(height[l] < x) {
  58. memset(val, -, sizeof(val));
  59. cnt = ;
  60. cnt += add(l, x);
  61. }
  62. else cnt += add(l, x);
  63. l++;
  64. if(cnt == *n) return true;
  65. }
  66. return false;
  67. }
  68. int main() {
  69. scanf("%d", &t);
  70. while(t--) {
  71. len = ;
  72. scanf("%d", &n);
  73. memset(vis, , sizeof(vis));
  74. for(int i = ; i <= n; i++) {
  75. scanf("%s", s);
  76. k = strlen(s);
  77. for(int j = ; j < k; j++) r[len++] = s[j]-'a'+;
  78. vis[len] = ;
  79. r[len++] = i;
  80. }
  81. for(int i = ; i < len; i++) vis[i] += vis[i-];
  82. SA(r, len, );
  83. int l = , r = 1e5;
  84. while(l <= r) {
  85. int mid = l+r>>;
  86. if(check(mid)) l = mid+;
  87. else r = mid-;
  88. }
  89. printf("%d\n", r);
  90. }
  91. }

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. java nio之Buffer

    一.JAVA NIO 是在和channel交互的时候使用的.Channel将数据读入缓冲区,然后我们又从缓冲区访问数据.写数据时,首先将要发送的数据按顺序填入缓冲区.基本上,缓冲区只是一个列表,它的所 ...

  2. js实现无限级分类

    let arr = [ {id:1,name:"php",pid:0}, {id:2,name:"php基础",pid:1}, {id:3,name:" ...

  3. web项目优化

    1 循环时没有使用break  案例:查找一个值是否在数组中存在(为举例舍弃自带函数) $aa=123; $arr=array(234,123,5,6,45646,346,23); foreach($ ...

  4. Spark mlib的本地向量

    Spark mlib的本地向量有两种: DenseVctor :稠密向量 其创建方式 Vector.dense(数据) SparseVector :稀疏向量 其创建方式有两种: 方法一:Vector. ...

  5. jetbrains系列激活

    没钱,只能DB了. 为了避免某些个人私自搭建服务器,以及自己搭建激活服务器,因此,决定使用破解包~~~. 注意:只要破解,就要屏蔽官方激活服务器:0.0.0.0 account.jetbrains.c ...

  6. 关闭Tomcat进程 一条语句(必看)

    写在开始 MAC系统下进行JAVA研发,经常遇到的一个问题就是杀死异常Tomcat 通常都是用两条指令,先查询出Tomcat占用的进程,再kill掉该进程, 其实有一种联合语句的方式可以一条语句直接关 ...

  7. 七:Web Application Proxy

    yarn自带了web接口,默认是和RM一起的(8088端口).但是为了减少从web接口受到的攻击,可以把Web接口单独放在别的机器上. 设置下web代理就行了 Configurations Confi ...

  8. appcan打包后产生的问题总结

    以appcan为基础的项目,最终需要打包后进行调试.在调试过程中,主要的样式问题在苹果手机上,下面将这些问题总结起来,以防下次再犯. 1:ios 7 以上的手机中,状态栏与内容重叠: 问题描述:在io ...

  9. html+css基础 - 个人备忘录

    //======================html部分===================// 表现内容<meta http-equiv="Content-Type" ...

  10. c# 编译的dll看不见注释问题

    1.项目属性---->生成----->勾选XML文档文件: 2.使用的时候该文件和dll放在一块.