Description

题库链接

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

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

Solution

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

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

用单调栈维护一下即可。

Code

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = (200000+5)<<1; char ch[N];
int s1, n, m, x[N<<1], y[N<<1], c[N], sa[N], rk[N], height[N];
ll ans, sum[N], a[N];
int s[N], top; void get() {
for (int i = 1; i <= n; i++) c[x[i] = ch[i]]++;
for (int i = 2; i <= m; i++) c[i] += c[i-1];
for (int i = n; i >= 1; i--) sa[c[x[i]]--] = i;
for (int k = 1; k <= n; k <<= 1) {
int num = 0;
for (int i = n-k+1; i <= n; i++) y[++num] = i;
for (int i = 1; i <= n; i++) if (sa[i] > k) y[++num] = sa[i]-k;
for (int i = 1; i <= m; i++) c[i] = 0;
for (int i = 1; i <= n; i++) c[x[i]]++;
for (int i = 2; i <= m; i++) c[i] += c[i-1];
for (int i = n; i >= 1; i--) sa[c[x[y[i]]]--] = y[i];
swap(x, y); x[sa[1]] = num = 1;
for (int i = 2; i <= n; i++)
x[sa[i]] = (y[sa[i]] == y[sa[i-1]] && y[sa[i]+k] == y[sa[i-1]+k]) ? num : ++num;
if ((m = num) == n) break;
}
for (int i = 1; i <= n; i++) rk[sa[i]] = i;
for (int i = 1, k = 0; i <= n; i++) {
if (rk[i] == 0) continue;
if (k) k--; int j = sa[rk[i]-1];
while (i+k <= n && j+k <= n && ch[i+k] == ch[j+k]) ++k;
height[rk[i]] = k;
}
}
void cal(int ss) {
top = 0;
for (int i = 1; i <= n; i++) sum[i] = sum[i-1]+(ss == (sa[i] > s1) && sa[i] != s1+1);
for (int i = 1; i <= n; i++) {
while (top && height[s[top]] >= height[i]) --top;
s[++top] = i; a[top] = a[top-1]+(sum[i-1]-sum[s[top-1]-1])*height[i];
if (ss == (sa[i] <= s1) && sa[i] != s1+1) ans += a[top];
}
}
void work() {
scanf("%s", ch+1); s1 = strlen(ch+1);
ch[s1+1] = '$'; scanf("%s", ch+s1+2);
n = strlen(ch+1); m = 255; get();
cal(0), cal(1); printf("%lld\n", ans);
}
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. LB+ECS+RDS经典架构图例及注意事项

    LB+ECS+RDS经典架构图例及注意事项

  2. Samba简介与配置(匿名&本地用户验证)

    Samba简介 Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件,由服务器及客户端程序构成. 在此之前我们已经了解了NFS,NFS与samba一样,也是在网络中实现文件共享的一种实 ...

  3. 测试快速关闭innodb的方法

    测试mysqlporformanceblog提供的减少关闭innodb时间的方法 经常发现一些MySQL镜像库的InnoDB的关闭时间会特别久,mysqlperformanceblog给出了一个不错的 ...

  4. shell脚本学习-变量

    跟着RUNOOB网站的教程学习的笔记 shell变量 shell变量的命名 定义变量时,变量名不加美元符号($,PHP语言中需要),如: name="runoob" 注意,变量名与 ...

  5. mysql data type <----> java data type (数值)

    https://dev.mysql.com/doc/refman/5.7/en/storage-requirements.html +----------------------------+---- ...

  6. SWPU-ACM集训队周赛之组队赛(3-11)G题题解

    点这里去做题 水水水水水,不难发现如下表 t 1 2 3 4 v 1 3 5 7 s 1 4 9 16 明显s=t*t 题目中对10000取模即取后四位,即对1000取余 #include<st ...

  7. Runtime之成员变量&属性&关联对象

    上篇介绍了Runtime类和对象的相关知识点,在4.5和4.6小节,也介绍了成员变量和属性的一些方法应用.本篇将讨论实现细节的相关内容. 在讨论之前,我们先来介绍一个很冷僻但又很有用的一个关键字:@e ...

  8. Js之设置日期时间 判断日期是否在范围内

    var now = new Date(); var startDate = new Date(); startDate.setFullYear(2018, 08, 07); startDate.set ...

  9. C++中const关键字 理解

    const:符号常量  使用符号常量写出的代码更容易维护:指针是边读边移动,而不是边写边移动,许多函数参数是只读不写的. const最常见用途是作为数组的界和switch分情况标号(也可以用枚举符代替 ...

  10. stm32驱动12832液晶屏程序(ST7565R控制器)

    LCD12832.c文件: #include"stm32f10x_lib.h" #include "OCM12232.h" void Lcd12232delay ...