@description@

给定两个长度为 n 的字符串 a, b 与一个长度为 m 的字符串 s。

问存在多少对区间 [l1, r1], [l2, r2](1 <= l1 <= r1 <= n, 1 <= l2 <= r2 <= n),使得:

1)两个区间含有交集。即存在 x 满足 l1 <= x <= r1 且 l2 <= x <= r2。

2)a[l1...r1] + b[l2...r2] = s。

原题传送门。

@solution@

区间要有交集,可以等价认为是 l1 <= r2 且 l2 <= r1。

由题,区间长度和 (r1 - l1 + 1) + (r2 - l2 + 1) = m。

变形一下得到 (r2 - l1 + 1) + (r1 - l2 + 1) = m。

结合上面要有交集的不等式,可以得到 1 <= (r2 - l1 + 1) < m。

我们使用 z-algorithm 求出 a 中每一个 l1 与 s 的最长公共前缀,求出 b 中每一个 r2 与 s 的最长公共后缀。

接着,从后往前扫描 a 中的每一个 l1,维护 x[i] 表示如果 r1 - l1 + 1 = i 时对应了多少 r2。查询只需要区间求和即可。

因为 1 <= (r2 - l1 + 1) < m,得到 r2 的取值范围实际上是个滑动的区间。每一个 r2 的贡献是一个区间加。

因此直接用树状数组即可。

@accepted code@

#include <cstdio>
#include <algorithm>
using namespace std; typedef long long ll; const int MAXN = 500000;
const int MAXM = 2*MAXN; int z[MAXM + MAXN + 5];
char str[MAXM + MAXN + 5]; void getZ(int len) {
int pos = 0, mxl = -1;
for(int i=1;i<len;i++) {
z[i] = (mxl >= i ? min(mxl - i + 1, z[i - pos]) : 0);
while( str[z[i]] == str[i+z[i]] ) z[i]++;
if( mxl < i + z[i] - 1 ) pos = i, mxl = i + z[i] - 1;
}
}
void get(char *S, int lenS, char *T, int lenT, int *f) {
for(int i=0;i<lenS;i++) str[i] = S[i];
str[lenS] = 1;
for(int i=0;i<lenT;i++) str[lenS+1+i] = T[i];
getZ(lenS + lenT + 1);
for(int i=0;i<lenT;i++) f[i] = z[lenS+1+i];
} int n, m; ll T[2][MAXM + 5];
int lowbit(int x) {return (x & -x);}
void add(int x, ll d, int t) {
for(int i=x;i<=m;i+=lowbit(i))
T[t][i] += d;
}
void modify(int l, int r, ll d) {
add(l, d, 0), add(l, d*l, 1);
add(r + 1, -d, 0), add(r + 1, -d*(r + 1), 1);
}
ll sum(int x, int t) {
ll ret = 0;
for(int i=x;i;i-=lowbit(i))
ret += T[t][i];
return ret;
}
ll query(int l, int r) {
ll A = l*sum(l - 1, 0) - sum(l - 1, 1);
ll B = (r + 1)*sum(r, 0) - sum(r, 1);
return B - A;
} char a[MAXN + 5], b[MAXN + 5], s[MAXM + 5];
int af[MAXN + 5], bf[MAXN + 5];
int main() {
scanf("%d%d%s%s%s", &n, &m, a, b, s);
get(s, m, a, n, af);
reverse(b, b + n), reverse(s, s + m);
get(s, m, b, n, bf);
reverse(bf, bf + n);
ll ans = 0;
for(int i=n-1;i>=0;i--) {
modify(max(m - bf[i], 1), m - 1, 1);
if( i + m - 1 < n )
modify(max(m - bf[i + m - 1], 1), m - 1, -1);
ans += query(1, af[i]);
}
printf("%lld\n", ans);
}

@details@

小清新的题目。

差点忘了树状数组的区间加与区间求和怎么写了。。。

@codefoces - 1313E@ Concatenation with intersection的更多相关文章

  1. [LeetCode] Intersection of Two Arrays II 两个数组相交之二

    Given two arrays, write a function to compute their intersection. Example:Given nums1 = [1, 2, 2, 1] ...

  2. [LeetCode] Intersection of Two Arrays 两个数组相交

    Given two arrays, write a function to compute their intersection. Example:Given nums1 = [1, 2, 2, 1] ...

  3. [LeetCode] Intersection of Two Linked Lists 求两个链表的交点

    Write a program to find the node at which the intersection of two singly linked lists begins. For ex ...

  4. [LeetCode] Substring with Concatenation of All Words 串联所有单词的子串

    You are given a string, s, and a list of words, words, that are all of the same length. Find all sta ...

  5. 【leetcode】Intersection of Two Linked Lists

    题目简述: Write a program to find the node at which the intersection of two singly linked lists begins. ...

  6. [LintCode] Intersection of Two Linked Lists 求两个链表的交点

    Write a program to find the node at which the intersection of two singly linked lists begins. Notice ...

  7. LeetCode Intersection of Two Arrays

    原题链接在这里:https://leetcode.com/problems/intersection-of-two-arrays/ 题目: Given two arrays, write a func ...

  8. Leetcode Substring with Concatenation of All Words

    You are given a string, S, and a list of words, L, that are all of the same length. Find all startin ...

  9. Intersection of Two Linked Lists

    Write a program to find the node at which the intersection of two singly linked lists begins. For ex ...

随机推荐

  1. Python_OpenCV学习记录01安装

    Python照样快! 众所周知,虽然Python语法简洁,编写高效,但相比C/C++运行慢很多.然 而Python还有个重要的特性:它是一门胶水语言!Python可以很容易地扩展 C/C++.Open ...

  2. vue路由中使用keep-alive 以及activated和deactivated 钩子

    本次只是记录下开发中碰到的问题. 最近做一个活动页面,涉及到角色和权限的问题,需要跳转很多页面,于是vue-router走起,顺便keep-alive也用起来了,嗯,跳转的很爽,但是一个详情页面组件, ...

  3. Life In Changsha College- 第四次冲刺

    第四次冲刺任务 整体功能实现. 用户故事 用户打开“生活在长大”的界面,选择登录 已注册过则输入用户名和密码直接登录 未注册用户则可选择注册功能,注册成功后登录 登录成功则弹出提示框 进行留言 系统结 ...

  4. try catch finally return 轶事

    最近阿里发布了java开发手册终极版,看到其中一条规约:[强制]不能在 finally 块中使用 return, finally 块中的 return 返回后方法结束执行,不会再执行 try 块中的 ...

  5. PAT1090 危险品装箱 (25分) ——值得留意的map用法(int型与vector型的关联)

    1090 危险品装箱 (25分)   集装箱运输货物时,我们必须特别小心,不能把不相容的货物装在一只箱子里.比如氧化剂绝对不能跟易燃液体同箱,否则很容易造成爆炸. 本题给定一张不相容物品的清单,需要你 ...

  6. position的值?

    static(默认):按照正常文档流进行排列:relative(相对定位):不脱离文档流,参考自身静态位置通过 top, bottom, left, right 定位:absolute(绝对定位):参 ...

  7. 【Flume】安装与测试

    1.下载安装包http://archive.apache.org/dist/flume/ 2.解压命令tar -zxvf 压缩包 -C 路径 3.配置环境变量 export FLUME_HOME=/o ...

  8. Java实现 LeetCode 786 第 K 个最小的素数分数(大小堆)

    786. 第 K 个最小的素数分数 一个已排序好的表 A,其包含 1 和其他一些素数. 当列表中的每一个 p<q 时,我们可以构造一个分数 p/q . 那么第 k 个最小的分数是多少呢? 以整数 ...

  9. Java 第十一届 蓝桥杯 省模拟赛 正整数的摆动序列

    正整数的摆动序列 问题描述 如果一个序列的奇数项都比前一项大,偶数项都比前一项小,则称为一个摆动序列.即 a[2i]<a[2i-1], a[2i+1]>a[2i]. 小明想知道,长度为 m ...

  10. Java实现 LeetCode 405 数字转换为十六进制数

    405. 数字转换为十六进制数 给定一个整数,编写一个算法将这个数转换为十六进制数.对于负整数,我们通常使用 补码运算 方法. 注意: 十六进制中所有字母(a-f)都必须是小写. 十六进制字符串中不能 ...