Description

题库链接

给定两个只含小写字母字符串 \(s_1,s_2\) ,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数。两个方案不同当且仅当这两个子串中有一个位置不同。

\(1\leq |s_1|,|s_2|\leq 200000\)

Solution

把两个串拼在一起,然后扫两遍。

第一遍统计所有的 \(B\) ,在它前面的 \(A\) 的贡献;第二遍统计所有的 \(A\) ,在它前面的 \(B\) 的贡献;

用单调栈维护一下即可。

Code

  1. #include <bits/stdc++.h>
  2. #define ll long long
  3. using namespace std;
  4. const int N = (200000+5)<<1;
  5. char ch[N];
  6. int s1, n, m, x[N<<1], y[N<<1], c[N], sa[N], rk[N], height[N];
  7. ll ans, sum[N], a[N];
  8. int s[N], top;
  9. void get() {
  10. for (int i = 1; i <= n; i++) c[x[i] = ch[i]]++;
  11. for (int i = 2; i <= m; i++) c[i] += c[i-1];
  12. for (int i = n; i >= 1; i--) sa[c[x[i]]--] = i;
  13. for (int k = 1; k <= n; k <<= 1) {
  14. int num = 0;
  15. for (int i = n-k+1; i <= n; i++) y[++num] = i;
  16. for (int i = 1; i <= n; i++) if (sa[i] > k) y[++num] = sa[i]-k;
  17. for (int i = 1; i <= m; i++) c[i] = 0;
  18. for (int i = 1; i <= n; i++) c[x[i]]++;
  19. for (int i = 2; i <= m; i++) c[i] += c[i-1];
  20. for (int i = n; i >= 1; i--) sa[c[x[y[i]]]--] = y[i];
  21. swap(x, y); x[sa[1]] = num = 1;
  22. for (int i = 2; i <= n; i++)
  23. x[sa[i]] = (y[sa[i]] == y[sa[i-1]] && y[sa[i]+k] == y[sa[i-1]+k]) ? num : ++num;
  24. if ((m = num) == n) break;
  25. }
  26. for (int i = 1; i <= n; i++) rk[sa[i]] = i;
  27. for (int i = 1, k = 0; i <= n; i++) {
  28. if (rk[i] == 0) continue;
  29. if (k) k--; int j = sa[rk[i]-1];
  30. while (i+k <= n && j+k <= n && ch[i+k] == ch[j+k]) ++k;
  31. height[rk[i]] = k;
  32. }
  33. }
  34. void cal(int ss) {
  35. top = 0;
  36. for (int i = 1; i <= n; i++) sum[i] = sum[i-1]+(ss == (sa[i] > s1) && sa[i] != s1+1);
  37. for (int i = 1; i <= n; i++) {
  38. while (top && height[s[top]] >= height[i]) --top;
  39. s[++top] = i; a[top] = a[top-1]+(sum[i-1]-sum[s[top-1]-1])*height[i];
  40. if (ss == (sa[i] <= s1) && sa[i] != s1+1) ans += a[top];
  41. }
  42. }
  43. void work() {
  44. scanf("%s", ch+1); s1 = strlen(ch+1);
  45. ch[s1+1] = '$'; scanf("%s", ch+s1+2);
  46. n = strlen(ch+1); m = 255; get();
  47. cal(0), cal(1); printf("%lld\n", ans);
  48. }
  49. int main() {work(); return 0; }

[HAOI 2016]找相同字符的更多相关文章

  1. [bzoj 4566][Haoi 2016]找相同字符

    传送门 Description 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两个子串中有一个位置不同. Solution 考虑用SAM,采用较为轻 ...

  2. BZOJ4566&&lg3181 HAOI找相同字符(广义后缀自动机)

    BZOJ4566&&lg3181 HAOI找相同字符(广义后缀自动机) 题面 自己找去 HINT 给定两个文本串,问从两个串中各取一个非空子串,使这俩子串相同,问方案有多少种.我的思路 ...

  3. BZOJ 4566: [Haoi2016]找相同字符 [后缀自动机]

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

  4. 【BZOJ4566】找相同字符(后缀数组)

    [BZOJ4566]找相同字符(后缀数组) 题面 BZOJ 题解 后缀数组的做法,应该不是很难想 首先看到两个不同的串,当然是接在一起求\(SA,height\) 那么,考虑一下暴力 在两个串各枚举一 ...

  5. 【BZOJ4566】找相同字符(后缀自动机)

    [BZOJ4566]找相同字符(后缀自动机) 题面 BZOJ 题解 看到多串处理,\(SA\)就连起来 \(SAM???\) 单串建自动机 然后其他串匹配 对于一个串建完\(SAM\)后 另一个串在\ ...

  6. bzoj4566 / P3181 [HAOI2016]找相同字符

    P3181 [HAOI2016]找相同字符 后缀自动机 (正解应是广义后缀自动机) 并不会广义后缀自动机. 然鹅可以用普通的后缀自动机.   我们先引入一个问题:算出从一个串内取任意两个不重合子串完全 ...

  7. 【BZOJ4566】[HAOI2016]找相同字符

    [BZOJ4566][HAOI2016]找相同字符 题面 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两个子串中有一个位置不同. 其中\(1\le ...

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

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

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

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

随机推荐

  1. 创建.NET core的守护进程

    http://www.cnblogs.com/savorboard/p/dotnetcore-supervisor.html

  2. loadtxt()函数的糟心历程

    原计划:导入一个csv文件,然后算出平均值 import numpy as np c=np.loadtxt('d:\python36\data.csv', delimiter=',', usecols ...

  3. MFC设置单文档保存格式以及标题

    在使用MFC编写单文档程序时,有时候需要将编辑的内容序列化为文件,使该文件可以直接以自己的程序打开,这时候需要在保存时将文件后缀改为我们想要的格式. 步骤 打开String Table,找到IDR_M ...

  4. 文件类File

    文件类File继承结构: public class File extends Object implements Serializable, Comparable<File> 常用方法: ...

  5. RxSwift学习笔记9:amb/tabkeWhile/tabkeUntil/skipWhile/skipUntil

    //amb基本介绍 //当传入多个 Observables 到 amb 操作符时,它将取第一个发出元素或产生事件的 Observable,然后只发出它的元素. //并忽略掉其他的 Observable ...

  6. Centos 执行top命令详细解读

    1.作用:top命令用来显示执行中的程序进程,使用权限是所有用户. 2.格式:top [-] [d delay] [q] [c] [S] [s] [i] [n] 3.主要参数: d:指定更新的间隔,以 ...

  7. InnoDB体系架构(一)后台线程

    InnoDB体系架构——后台线程 上一篇已经了解了MySQL数据库的体系结构 这一篇除了介绍InnoDB存储引擎的体系架构外,同时进一步了解InnoDB的后台线程. InnoDB存储引擎是多线程的模型 ...

  8. 第二十节:详细讲解String和StringBuffer和StringBuilder的使用

    前言 在 Java中的字符串属于对象,那么Java 中提供了 String 类来创建和操作字符串,即是使用对象:因为String类修饰的字符一旦被创建就不可改变,所以当对字符串进行修改的时候,需要使用 ...

  9. Swift5 语言指南(十九) 错误处理

    错误处理是响应程序中的错误条件并从中恢复的过程.Swift为在运行时抛出,捕获,传播和操纵可恢复的错误提供了一流的支持. 某些操作无法保证始终完成执行或生成有用的输出.Optionals用于表示缺少值 ...

  10. Linux链接脚本学习--lds

    一.概论 ld: GNU的链接器. 用来把一定量的目标文件跟档案文件链接在一起,并重新定位它们的数据,链接符号引用. 一般编译一个程序时,最后一步就是运行ld进行链接 每一个链接都被一个链接脚本所控制 ...