题面

有两个串\(A\)和\(B\),长度分别为\(n\)和\(m\),只含'Z','P','S','B'四个大写字母,定义\(B\)在第\(p\)位(\(0 \le p \le n - m\))匹配\(A\)为对\(B\)的每个位置\(B_i\),在\(A_{\max (0, p + i - k)}\)到\(A_{min(n - 1, p + i + k)}\)中都存在与\(B_i\)相同的字符,现给出\(A\),\(B\)和\(k\),问\(B\)在多少个位置和\(A\)匹配

题外话

怕是几天来改得最快的一道题了……

解析

只有四个字母,就考虑分开处理

枚举每个字符

设\(a_i\)表示\(A\)串的第\(i\)个位置能不能匹配这个字符,\(b_i\)表示\(B\)串的第\(i\)个位置是否是这个字符(\(a_i, b_i\)都是\(0/1\))

那么\(p\)位置能匹配的位置数量就是\(\sum_{i = 0}^{m - 1} b_i \cdot a_{p + i} = \sum_{i = 0}^{n - p - 1} b_i \cdot a_{p + i}\),上界可以扩展因为\(m - 1\)之后的位置\(b\)为\(0\),不会影响结果

设这个式子为\(f(p)\),把\(a_i\)翻转一下,即\(g(i) = a_{n - 1 - i}\),那么:
\[ \begin{align} f(p) & = \sum_{i = 0}^{n - p - 1} b_i\cdot a_{p + i} \\ & = \sum_{i = 0}^{n - p - 1} b_i \cdot g(n - p - 1 - i) \end{align} \]
然后把\(f\)翻转,得到:
\[ f(n - 1 - p) = \sum_{i = 0}^{n - p - 1} b_i \cdot g(n - p - 1 - i) \]
这不就是个卷积吗,\(FFT\)或者\(NTT\)都可以做

对每个字符求出各个位置能匹配的数量,显然只有当一个位置各个字符匹配数量的和为\(m\)的时候\(B\)才能在这个位置匹配\(A\),最后判一下统计答案就行了

代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
#define MAXN 200005typedef long long LL;
const int mod = 998244353;
const char set[] = {'Z', 'P', 'S', 'B'};int qpower(int, int, int);
void pre_rev(int);
void NTT(int *, int, int);int K, n, m, ans, match[MAXN], rev[MAXN << 2], f[MAXN << 2], g[MAXN << 2];
char A[MAXN], B[MAXN];inline void inc(int &x, int y) { x += y; if (x >= mod) x -= mod; }
inline void dec(int &x, int y) { x -= y; if (x < 0) x += mod; }
inline int add(int x, int y) { x += y; return x >= mod ? x - mod : x; }
inline int sub(int x, int y) { x -= y; return x < 0 ? x + mod : x; }int main() {freopen("base.in", "r", stdin);freopen("base.out", "w", stdout);scanf("%d%s%s", &K, A, B);n = strlen(A), m = strlen(B);if (m > n) { puts("0"); return 0; }for (int i = 0; i < 4; ++i) {memset(f, 0, sizeof f); memset(g, 0, sizeof g);for (int j = 0, last = -1; j < n; ++j) {if (A[j] == set[i]) last = j;if ((~last) && last >= j - K) g[j] = 1;}for (int j = n - 1, last = -1; j >= 0; --j) {if (A[j] == set[i]) last = j;if((~last) && last <= j + K) g[j] = 1;}for (int j = 0; j < m; ++j)if (B[j] == set[i]) f[j] = 1;std::reverse(g, g + n);int sz;for (sz = 0; (1 << sz) < (n << 1); ++sz);pre_rev(sz);NTT(f, sz, 1); NTT(g, sz, 1);for (int i = 0; i < (1 << sz); ++i) f[i] = (LL)f[i] * g[i] % mod;NTT(f, sz, -1);for (int i = 0; i <= n - m; ++i) inc(match[i], f[n - 1 - i]);//debug//for (int i = 0; i <= n - m; ++i) printf("%d ", f[n - 1 - i]);//puts("");}for (int i = 0; i <= n - m; ++i) if (match[i] == m) ++ans;printf("%d\n", ans);return 0;
}
int qpower(int x, int y, int p) {int res = 1;while (y) {if (y & 1) res = (LL)res * x % p;x = (LL)x * x % p; y >>= 1;}return res;
}
void NTT(int *arr, int sz, int tp) {for (int i = 0; i < (1 << sz); ++i)if (rev[i] > i) std::swap(arr[i], arr[rev[i]]);for (int len = 2, half = 1; len <= (1 << sz); len <<= 1, half <<= 1) {int wn = qpower(3, (mod - 1) / len, mod);if (tp == -1) wn = qpower(wn, mod - 2, mod);for (int i = 0; i < (1 << sz); i += len) {int w = 1;for (int j = 0; j < half; ++j, w = (LL)w * wn % mod) {int x = arr[i + j], y = (LL)arr[i + j + half] * w % mod;inc(arr[i + j], y); dec(arr[i + j + half] = x, y);}}}if (tp == -1) {int inv = qpower(1 << sz, mod - 2, mod);for (int i = 0; i < (1 << sz); ++i) arr[i] = (LL)arr[i] * inv % mod;}
}
inline void pre_rev(int sz) {for (int i = 0; i < (1 << sz); ++i) rev[i] = ((rev[i >> 1] >> 1) | ((i & 1) << sz - 1));
}
//Rhein_E

转载于:https://www.cnblogs.com/Rhein-E/p/10524007.html

day10T1改错记相关推荐

  1. day16T2改错记

    题目描述 给出\(n\)个串,你要从每个串中抽出一个子串(可以是空串),把他们拼接起来,问: 按字典序输出所有可能的结果(包括空串) 输出总共有多少种不同的结果(包括空串),对\(1e9+7\)取模 ...

  2. 2019年北京理工大学计算机专硕上岸经验分享

    2019年北京理工大学计算机专硕上岸经验分享 上午十一点出的名单,终于放下心了.静下心来记录下经验.希望能帮到学弟学妹们. 先贴两个比较重要的链接: 北京理工大学复试上机题汇总 历年北京理工大学复试专 ...

  3. HBTS(HBOI) 2019 真实退役记

    Day 0 早上迷迷糊糊醒了不知道多久,反正差不多的时间被叫醒了,然后走去了火车站. 这次终于取到了蓝色的车票,以前去武汉的车票都取的红色不知道为什么-- 在火车上看了<悲伤逆流成河>,稍 ...

  4. Java学习笔记,面向猴子记笔记2021/5/29更新

    如何在 3 天内学会 Java? https://www.zhihu.com/question/66535555/answer/1799868707 (手动滑稽) 在编辑器中鼠标右键source可以快 ...

  5. 《高质量程序设计指南——C/C++语言》之开篇记

    <高质量程序设计指南--C/C++语言>是林锐博士和韩永泉先生撰写的著作,记得刚毕业那会读过了.应该说,这本书是对学校教科书的一个很好补充和提高.关于C/C++的经典书籍,国外已经有很多很 ...

  6. 高一4月段考GDOI2021划水记 总结

    文章目录 P r e f a c e Preface Preface 段考 Day -4 Day -3 Day -2&Day -1 GDOI Day 0 Day 1 Day 2 R e s u ...

  7. [置顶] 记一个应届生的求职旅途

    记一个应届生的求职旅途 见有些同学发状态说大学期间要1.过四级2.拿到会计证,然后说了句毕业找工作去联通电信..我就纳闷了,有没有点常识,1.过四级是大学生的最低标准,很多企业单位根本跟英语没半毛钱关 ...

  8. 湖南工业大学c语言 期末考试程序改错,高考各科答题规范,90%的同学都不了解!现在改还来得及!...

    前 言 考试答题,对分数影响最为关键的就是答案的正确性.但是很多学生在考试后却依然会有些意见:因为自己答案正确却没拿到满分.是阅卷的不公正么?当然不是! 很多时候,其实是你忽略了答题的规范性.越是大型 ...

  9. 去除html标签 express,详解Express条记之静态衬着HTML(新脚进坑)

    在日常项目中,我喜欢用Django做后端, 因为大而全 如果只是写一个简单服务的话, Express是更好的选择, Express是基于nodejs的一个后端框架,特点是简单,轻量, 容易搭建, 而且 ...

最新文章

  1. 软件测试2019:第四次作业
  2. HDU 1258 Sum It Up
  3. 浅谈ORACLE AWR single instance 一
  4. Entity Framework 4.1(转)
  5. Android 条码扫描程序源码
  6. 个人觉的不错的文章[来自CSDN]
  7. 开博1个月不到,照样可以申请到text-link-ads
  8. 常见Web安全漏洞及防范
  9. mysql更新记录_如何查看 mysql 表中最近更新的记录
  10. 如何使用计算机讲解ppt,如何录制PPT讲解视频?
  11. potainer 日志_分享10个优秀的日志分析工具
  12. 【fiddler手机抓包不能上网问题解决】
  13. 全球及中国游戏耳机行业销售模式与动态盈利分析报告2022版
  14. 解决IDEA输入ctrl+空格,和输入法冲突的问题
  15. ad设置塞孔_超实用!PCB设计中过孔常用的6种处理方式
  16. httpd离线安装(含依赖包下载地址)
  17. 微信小程序、uni-app使用iconfont-tools将iconfont彩色字体图标组件化并使用
  18. 【游戏编程扯淡精粹】游戏编程设计模式
  19. pycharm3.6.5安装不了cfg包(求解)
  20. 在首席架构师眼里,架构的本质

热门文章

  1. MySQL的存储引擎InnoDB,B+Tree数据结构索引的实现原理图(聚簇索引/聚集索引)
  2. arpanet(阿帕网)
  3. IntelliJ IDEA for Mac 如何设置 tab 键为 4 个空格?
  4. PL/SQL工具执行SQL脚本文件
  5. SpringBoot JPA
  6. opencv 把3通道图像转成单通道_小强学Python+OpenCV之-1.4.3图像(矩阵)加减运算
  7. 不需要软著的安卓应用市场_哪些安卓应用市场上架应用比较简单啊,不需要软著啊?公司开发的 APP 着急上架...
  8. mysql函数和索引冲突问题_Mysql索引常见问题汇总
  9. opencv yuv保存本地_OpenCV-dlib-python3实现人脸戴墨镜和含Y的抖音效果
  10. C语言应用笔记:C语言typedef关键字及其使用