【BZOJ4566】[HAOI2016]找相同字符

题面

给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数。两个方案不同当且仅当这两个子串中有一个位置不同。

其中\(1\leq|s1|,|s2|\leq n\)

题解

其实和这题差不多。

根据后缀数组常用套路,将将\(s1,s2\)用一个未曾出现的字符连起来

和上面那题一样的方法

算出来一个答案

然后减去分别左右两字符串选的贡献就好啦

代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <cmath>
  6. #include <algorithm>
  7. using namespace std;
  8. const int MAX_N = 4e5 + 5;
  9. int N; char a[MAX_N], b[MAX_N], c[MAX_N];
  10. int sa[MAX_N], rnk[MAX_N], lcp[MAX_N];
  11. void GetSA() {
  12. #define cmp(i, j, k) (y[i] == y[j] && y[i + k] == y[j + k])
  13. static int x[MAX_N], y[MAX_N], bln[MAX_N];
  14. int M = 122;
  15. for (int i = 0; i <= M; i++) bln[i] = 0;
  16. for (int i = 1; i <= N; i++) bln[x[i] = a[i]]++;
  17. for (int i = 1; i <= M; i++) bln[i] += bln[i - 1];
  18. for (int i = N; i >= 1; i--) sa[bln[x[i]]--] = i;
  19. for (int k = 1; k <= N; k <<= 1) {
  20. int p = 0;
  21. for (int i = 0; i <= M; i++) y[i] = 0;
  22. for (int i = N - k + 1; i <= N; i++) y[++p] = i;
  23. for (int i = 1; i <= N; i++) if (sa[i] > k) y[++p] = sa[i] - k;
  24. for (int i = 0; i <= M; i++) bln[i] = 0;
  25. for (int i = 1; i <= N; i++) bln[x[y[i]]]++;
  26. for (int i = 1; i <= M; i++) bln[i] += bln[i - 1];
  27. for (int i = N; i >= 1; i--) sa[bln[x[y[i]]]--] = y[i];
  28. swap(x, y); x[sa[1]] = p = 1;
  29. for (int i = 2; i <= N; i++) x[sa[i]] = cmp(sa[i], sa[i - 1], k) ? p : ++p;
  30. if (p >= N) break;
  31. M = p;
  32. }
  33. }
  34. void GetLcp() {
  35. for (int i = 1; i <= N; i++) rnk[sa[i]] = i;
  36. for (int i = 1, j = 0; i <= N; i++) {
  37. if (j) --j;
  38. while (a[i + j] == a[sa[rnk[i] - 1] + j]) ++j;
  39. lcp[rnk[i]] = j;
  40. }
  41. }
  42. typedef long long ll;
  43. int lp[MAX_N], rp[MAX_N], stk[MAX_N], top;
  44. ll solve() {
  45. GetSA(), GetLcp();
  46. top = 0, stk[0] = 1;
  47. for (int i = 2; i <= N; i++) {
  48. while (top > 0 && lcp[stk[top]] >= lcp[i]) --top;
  49. lp[i] = i - stk[top], stk[++top] = i;
  50. }
  51. top = 0, stk[0] = N + 1;
  52. for (int i = N; i >= 2; i--) {
  53. while (top > 0 && lcp[stk[top]] > lcp[i]) --top;
  54. rp[i] = stk[top] - i, stk[++top] = i;
  55. }
  56. ll res = 0;
  57. for (int i = 2; i <= N; i++) res += 1ll * lp[i] * rp[i] * lcp[i];
  58. return res;
  59. }
  60. int main () {
  61. ll ans = 0; int n, m;
  62. scanf("%s", b + 1); scanf("%s", c + 1);
  63. n = strlen(b + 1); m = strlen(c + 1);
  64. N = n; for (int i = 1; i <= N; i++) a[i] = b[i];
  65. ans -= solve();
  66. N = m; for (int i = 1; i <= N; i++) a[i] = c[i];
  67. ans -= solve();
  68. N = n + m + 1;
  69. for (int i = 1; i <= n; i++) a[i] = b[i];
  70. a[n + 1] = '#';
  71. for (int i = 1; i <= m; i++) a[i + n + 1] = c[i];
  72. ans += solve();
  73. printf("%lld\n", ans);
  74. return 0;
  75. }

【BZOJ4566】[HAOI2016]找相同字符的更多相关文章

  1. BZOJ4566 [Haoi2016]找相同字符【SAM】

    BZOJ4566 [Haoi2016]找相同字符 给定两个字符串\(s和t\),要求找出两个字符串中所有可以相互匹配的子串对的数量 首先考虑可以怎么做,我们可以枚举\(t\)串的前缀\(t'\),然后 ...

  2. [BZOJ4566][Haoi2016]找相同字符 后缀自动机+dp

    4566: [Haoi2016]找相同字符 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1212  Solved: 694[Submit][Stat ...

  3. [Bzoj4566][Haoi2016]找相同字符(广义后缀自动机)

    4566: [Haoi2016]找相同字符 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 861  Solved: 495[Submit][Statu ...

  4. BZOJ4566 [Haoi2016]找相同字符 字符串 SAM

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ4566.html 题目传送门 - BZOJ4566 题意 给定两个字符串 $s1$ 和 $s2$ ,问有 ...

  5. BZOJ4566: [Haoi2016]找相同字符

    Description 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两 个子串中有一个位置不同. Input 两行,两个字符串s1,s2,长度分别 ...

  6. BZOJ4566: [Haoi2016]找相同字符(后缀自动机)

    题意 题目链接 Sol 直接在SAM上乱搞 枚举前缀,用SAM统计可以匹配的后缀,具体在匹配的时候维护和当前节点能匹配的最大值 然后再把parent树上的点的贡献也统计上,这部分可以爆跳parent树 ...

  7. BZOJ4566 Haoi2016 找相同字符【广义后缀自动机】

    Description 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两 个子串中有一个位置不同. Input 两行,两个字符串s1,s2,长度分别 ...

  8. BZOJ4566:[HAOI2016]找相同字符(SAM)

    Description 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两 个子串中有一个位置不同. Input 两行,两个字符串s1,s2,长度分别 ...

  9. BZOJ4566 [Haoi2016]找相同字符 【后缀数组】

    题目 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两 个子串中有一个位置不同. 输入格式 两行,两个字符串s1,s2,长度分别为n1,n2.1 & ...

  10. BZOJ4566 HAOI2016找相同字符(后缀自动机)

    对第一个串建SAM,第二个串在上面跑,记录当前前缀匹配的最长后缀长度l,每次考虑当前前缀的贡献,对于当前所在节点显然是|right|*(l-len[fa]),而对于其parent树上所有祖先的贡献显然 ...

随机推荐

  1. hdu-3397 Sequence operation 线段树多种标记

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3397 题目大意: 0 a b表示a-b区间置为0 1 a b表示a-b区间置为1 2 a b表示a- ...

  2. iOS绘图事务的运行验证

    结合WWDC,以我们的call stack为例,来说明这四个过程分别大概都做了什么. layout过程 从上面layout的过程可以看出,其所做的主要任务就是将图层调用代理(也就是视图)实现整个视图层 ...

  3. CSS(层叠样式表)基础知识

     CSS 指层叠样式表 (Cascading Style Sheets).样式定义怎样显示 HTML 元素.它通常存储在样式表中,把样式加入到 HTML 4.0 中,解决内容与表现分离的问题. 当同一 ...

  4. mongd配置文件解释

    mongd配置文件解释 系统日志配置 systemLog: verbosity: <int> quiet: <boolean> traceAllExceptions: < ...

  5. Struts2框架学习笔记--strtus2初识

    struts2概述: 1.struts2框架应用于javaEE三层结构中的Web层框架 2.struts2框架是在struts1和webwork基础之上发展的全新框架(脱胎换骨 ,用法完全不一样)ps ...

  6. redis 安装 配置 及启动

    linux下安装redis及其中遇到的问题的解决方法1.将下载好的压缩包放到/usr/local目录下# tar xzf redis-3.0.2.tar.gz# cd redis-3.0.2# mak ...

  7. OO 第三次博客总结

    调研规格化设计 1950年代,第一次分离,主程序和子程序的分离程序结构模型是树状模型,子程序可先于主程序编写.通过使用库函数来简化编程,实现最初的代码重用.产生基本的软件开发过程:分析—设计—编码—测 ...

  8. VirtualBox + CentOS详细安装教程

    一.前期工作准备 电脑虚拟化开启(必要工作)大致流程: a.电脑开机时长按F12(F10)进入BIOS界面; b.依次选择Configuratio > Intel Virtual Technol ...

  9. Delphi Compiler Bug?

    I found a Bug of Delphi XE3 Compiler,It may exists in XE4,XE5. Here is the code to show the bug proc ...

  10. 关于uip中的log和打印

    简单易用,好区分 void uip_log(char *m){ printf("uIP log message: %s\n", m);}