求多串的最长公共字串.

法1: 二分长度+hash 传送门

法2: 二分+后缀数组 传送门

法3: 后缀自动机

拿第一个串建自动机,然后用其他串在上面匹配.每次求出SAM上每个节点的最长匹配长度后,再在全局取最小值(因为是所有串的公共串)就行了.

CODE

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. char cb[1<<15],*cs=cb,*ct=cb;
  4. #define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
  5. template<class T>inline void read(T &res) {
  6. char ch; int flg = 1; while(!isdigit(ch=getchar()))if(ch=='-')flg=-flg;
  7. for(res=ch-'0';isdigit(ch=getchar());res=res*10+ch-'0'); res*=flg;
  8. }
  9. const int MAXN = 2005;
  10. const int C = 26;
  11. int m, lk[MAXN<<1], ch[MAXN<<1][C], len[MAXN<<1], mx[MAXN<<1], mn[MAXN<<1], bin[MAXN<<1], seq[MAXN<<1], sz, last;
  12. inline void init() {
  13. last = sz = 0; ++sz;
  14. lk[0] = -1; len[0] = 0;
  15. }
  16. inline void Copy(int A, int B) {
  17. lk[A] = lk[B];
  18. memcpy(ch[A], ch[B], sizeof ch[B]);
  19. }
  20. inline int insert(int p, int c) {
  21. int cur = sz++; last = cur;
  22. len[cur] = len[p] + 1;
  23. for(; ~p && !ch[p][c]; p = lk[p]) ch[p][c] = cur;
  24. if(p == -1) lk[cur] = 0;
  25. else {
  26. int q = ch[p][c];
  27. if(len[p] + 1 == len[q]) lk[cur] = q;
  28. else {
  29. int x = sz++;
  30. len[x] = len[p] + 1;
  31. Copy(x, q);
  32. lk[cur] = lk[q] = x;
  33. for(; ~p && ch[p][c] == q; p = lk[p]) ch[p][c] = x;
  34. }
  35. }
  36. return last;
  37. }
  38. inline void Match(char *s) {
  39. int p = 0, now = 0, j = 0;
  40. for(int c; s[j]; ++j) {
  41. if(ch[p][c=s[j]-'a'])
  42. ++now, p = ch[p][c];
  43. else {
  44. for(; ~p && !ch[p][c]; p = lk[p]);
  45. if(p == -1) now = p = 0;
  46. else now = len[p] + 1, p = ch[p][c];
  47. }
  48. mx[p] = max(mx[p], now);
  49. }
  50. for(int i = sz-1; i; --i) {
  51. mn[seq[i]] = min(mn[seq[i]], mx[seq[i]]);
  52. mx[lk[seq[i]]] = max(mx[lk[seq[i]]], mx[seq[i]]);
  53. mx[seq[i]] = 0;
  54. }
  55. }
  56. char s[MAXN];
  57. int main() {
  58. read(m); scanf("%s", s);
  59. if(--m == 0) return printf("%d\n", strlen(s)), 0;
  60. init(); int p = 0;
  61. for(int i = 0; s[i]; ++i) p = insert(p, s[i]-'a');
  62. for(int i = 0; i < sz; ++i) ++bin[mn[i] = len[i]];
  63. for(int i = 1; i < sz; ++i) bin[i] += bin[i-1];
  64. for(int i = sz-1; ~i; --i) seq[--bin[len[i]]] = i;
  65. while(m--) scanf("%s", s), Match(s);
  66. int ans = 0;
  67. for(int i = 1; i < sz; ++i)
  68. ans = max(ans, mn[i]);
  69. printf("%d\n", ans);
  70. }

BZOJ 2946 [Poi2000]公共串 (二分+Hash/二分+后缀数组/后缀自动机)的更多相关文章

  1. BZOJ 2946: [Poi2000]公共串

    2946: [Poi2000]公共串 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 787  Solved: 342[Submit][Status][D ...

  2. BZOJ 2946: [Poi2000]公共串( 后缀自动机 )

    一个串建后缀自动机, 其他串在上面跑, 然后用当前串跑的去更新全部 ------------------------------------------------------------------ ...

  3. bzoj 2946: [Poi2000]公共串【SAM】

    对第一个串建SAM,把剩下的串在上面跑,每次跑一个串的时候在SAM的端点上记录匹配到这的最大长度,然后对这些串跑的结果取min,然后从这些节点的min中取max就是答案 注意在一个点更新后它的祖先也会 ...

  4. bzoj 2946 [Poi2000]公共串——后缀自动机

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2946 对每个串都建一个后缀自动机,然后 dfs 其中一个自动机,记录同步的话在别的自动机上走 ...

  5. BZOJ 2946 POI2000 公共串 后缀自动机(多串最长公共子串)

    题意概述:给出N个字符串,每个串的长度<=2000(雾...可能是当年的年代太久远机子太差了),问这N个字符串的最长公共子串长度为多少.(N<=5) 抛开数据结构,先想想朴素做法. 设计一 ...

  6. BZOJ 2946 [Poi2000]公共串 ——后缀自动机

    任意选择一个串作为模式串,构建出后缀自动机. 然后用其他的串在后缀自动机上跑匹配. 然后就到了理解后缀自动机性质的时候. 在某一个节点的最大值是可以沿着parent树上传的. 然后用dp[i][j]表 ...

  7. 【BZOJ 2946】 2946: [Poi2000]公共串 (SAM)

    2946: [Poi2000]公共串 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1063  Solved: 469 Description      ...

  8. 【BZOJ】2946: [Poi2000]公共串

    http://www.lydsy.com/JudgeOnline/problem.php?id=2946 题意:给n个串,求最大公共子串.(1<=n<=5,每个串长度<=2000) ...

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

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

随机推荐

  1. centos7安装oracle1201c

    root身份安装依赖包: yum -y install binutils compat-libcap1 compat-libstdc++-33 compat-libstdc++-33*.i686 el ...

  2. IE浏览器的脚本文本框监听事件

    一.IE8的文本框监听事件 由于在IE8所以input和propertychange都不能用,终于皇天不负有心人让我找到了这个:https://github.com/sophiebits/jquery ...

  3. linux 软连接和 硬链接的区别

    Linux软链接硬链接的区别   ln是linux中又一个非常重要命令,它的功能是为某一个文件在另外一个位置建立一个同步的链接.当我们需要在不同的目录,用到相同的文件时,我们不需要在每一个需要的目录下 ...

  4. n*n矩阵 每行每列XOR为0(思维)

    题意:https://codeforc.es/contest/1208/problem/C 如题:就是给定一个数n,要你求一个n×n的矩阵,矩阵中的元素是 0 ~ n2-1 ,使得矩阵每一行和每一列的 ...

  5. GET POST请求区别

    cookie .session.tokencookie:存放在浏览器相关的硬盘文件中session:存放在服务器端的内存中,退出后,被清空token:服务器端生成后,不保存,发给客户端,客户端的hea ...

  6. Java 注解(原理及其使用)

    一.注解(annotation)介绍 Java在JDK5中引入源代码的注解机制. 1.什么是注解? 注解为代码添加了元数据,元数据是关于数据的组织.数据域及其关系的说明信息. 更通俗的说,注解为程序元 ...

  7. 【vue】computed 和 watch

    计算属性:computed  监听多个变量且变量是在vue实例中(依赖某个变量,变量发生改变就会触发) 侦听器:   watch        监听一个变量的变化 使用场景:watch(异步场景)  ...

  8. JS基础_for循环练习1

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

  9. 深入理解hive(1)

    1.安装和配置: 1.1可以通过这个下载链接去下载hive源码来安装一个一个稳定版本的hive.https://cwiki.apache.org/confluence/display/Hive/Get ...

  10. JavaScript函数尾调用与尾递归

    什么是函数尾调用和尾递归 函数尾调用与尾递归的应用 一.什么是函数的尾调用和尾递归 函数尾调用就是指函数的最后一步是调用另一个函数. //函数尾调用示例一 function foo(x){ retur ...