CH1809 匹配统计 题解
看了好久才懂,我好菜啊……
题意:给两个字符串 \(a\) 与 \(b\),对于 \(q\) 次询问,每次询问给出一个 \(x\),求存在多少个位置使得 \(a\) 从该位置开始的后缀子串与 \(b\) 匹配的长度恰好为 \(x\)。
这题可以 Hash+二分 \(O(n\log n)\) 过,还有一个高端做法是扩展 KMP(然而并不会
正解的话,还是 KMP。但此题对 KMP 的理解还是要求很高啊。
对 \(b\) 求一遍 \(nxt\),再求 \(a\) 的 \(f\)。那么根据定义,\(f_i=j\) 表示 \(a_{i-j+1\sim i}=b_{1\sim j}\),换句话说,\(a\) 从 \(i-j+1\) 开始的后缀与 \(b\) 的匹配长度至少为 \(j\)。
由于我们只是求出了至少,但题目问的是精确值,那么做一个转换,开一个桶 \(cnt\),\(cnt_i\) 表示匹配长度至少为 \(i\) 的位置有几个,那么对于每一个询问,答案就是 \(cnt_x-cnt_{x+1}\)。
求完 \(f\) 后,我们把它扔进桶里。
还没完,考虑一下到现在为止 \(cnt\) 里存了什么,我们发现现在的 \(cnt_i\) 存的位置个数并没有覆盖所有的情况,也就是说我们要做一个后缀和来覆盖这些情况。
如何做后缀和?根据 KMP 的性质,如果 \(a[i-j+1\sim i]=b[1\sim j]\),那么 \(a[i-j+1\sim i-j+nxt[j]]=b[1\sim nxt[j]]\) 同样成立,并且中间的都不成立,也就是说,\(nxt[j]\) 是次选项。进一步地,\(nxt[nxt[j]],nxt[nxt[nxt[j]]],...\)都是满足条件的选项,这样我们的答案就得到了扩展并覆盖了所有情况。
所以我们倒序枚举 \(m\),后缀和的递推式就是cnt[nxt[i]]+=cnt[i]。
本题真心很难理解(好像字符串题就没有好理解的),一定要多画图,把抽象描述形象化。
#include <cstdio>
#include <cstring>
using namespace std;
const int N=2e5+5;
int n,m,q,nxt[N],f[N],cnt[N];
char a[N],b[N];
int main()
{
scanf("%d%d%d",&n,&m,&q);
scanf("%s %s",a+1,b+1);
for(int i=2,j=0;i<=m;++i)
{
while(j>0&&b[i]!=b[j+1]) j=nxt[j];
if(b[i]==b[j+1]) ++j;
nxt[i]=j;
}
for(int i=1,j=0;i<=n;++i)
{
while(j>0&&a[i]!=b[j+1]) j=nxt[j];
if(a[i]==b[j+1]) ++j;
f[i]=j;
}
for(int i=1;i<=n;++i) ++cnt[f[i]];
for(int i=m;i;--i) cnt[nxt[i]]+=cnt[i];
while(q--)
{
int x; scanf("%d",&x);
printf("%d\n",cnt[x]-cnt[x+1]);
}
return 0;
}
CH1809 匹配统计 题解的更多相关文章
- CH1809匹配统计【KMP】
1809 匹配统计 0x18「基本数据结构」练习 描述 阿轩在纸上写了两个字符串,分别记为A和B.利用在数据结构与算法课上学到的知识,他很容易地求出了“字符串A从任意位置开始的后缀子串”与“字符串B” ...
- CH1809 匹配统计
题意 描述 阿轩在纸上写了两个字符串,分别记为A和B.利用在数据结构与算法课上学到的知识,他很容易地求出了"字符串A从任意位置开始的后缀子串"与"字符串B"匹配 ...
- 洛谷P2891 Dining P1402 酒店之王【类二分图匹配】题解+代码
洛谷P2891 Dining P1402 酒店之王[类二分图匹配]题解+代码 酒店之王 题目描述 XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化.由于很多来住店的旅客有自己喜好的 ...
- 【CH1809】匹配统计(KMP)
题目链接 摘自https://www.cnblogs.com/wyboooo/p/9829517.html 用KMP先求出以a[i]为结尾的前缀与b匹配的最长长度. 比如 f[i] = j,就表示a[ ...
- 洛谷P2756飞行员配对方案问题 P2055假期的宿舍【二分图匹配】题解+代码
洛谷 P2756飞行员配对方案问题 P2055假期的宿舍[二分图匹配] 飞行员配对方案问题 题目背景 第二次世界大战时期.. 题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架 ...
- C#版 - PAT乙级(Basic Level)真题 之 1021.个位数统计 - 题解
版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - P ...
- POJ 2400 Supervisor, Supervisee(KM二分图最大权值匹配)题解
题意:n个老板n个员工,先给你n*n的数据,i行j列代表第i个老板第j喜欢的员工是谁,再给你n*n的数据,i行j列代表第i个员工第j喜欢的老板是谁,如果匹配到第k喜欢的人就会产生一个分数k-1.现在让 ...
- 洛谷P1554 梦中的统计 题解
题目传送门 这道题暴力又让我过了...数据真的很水(luogu) 暴力枚举n~m的每个数,再统计一次,交付评测...AC #include<bits/stdc++.h> using nam ...
- BZOJ3992:[SDOI2015]序列统计——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=3992 https://www.luogu.org/problemnew/show/P3321 小C ...
随机推荐
- 【NX二次开发】Block UI 整数表
属性说明 常规 类型 描述 BlockID String 控件ID Enable Logical 是否可操作 Group Logical ...
- 【NX二次开发】获得屏幕矩阵并设置WCS为屏幕方向
说明:获得屏幕矩阵并设置WCS为屏幕方向(Z朝向自己,X轴朝右,Y轴超上). 方法: 1 extern DllExport void ufusr(char *param, int *retcode, ...
- Qt中的多线程与线程池浅析+实例
1. Qt中的多线程与线程池 今天学习了Qt中的多线程和线程池,特写这篇博客来记录一下 2. 多线程 2.1 线程类 QThread Qt 中提供了一个线程类,通过这个类就可以创建子线程了,Qt 中一 ...
- Python小白的数学建模课-09 微分方程模型
小白往往听到微分方程就觉得害怕,其实数学建模中的微分方程模型不仅没那么复杂,而且很容易写出高水平的数模论文. 本文介绍微分方程模型的建模与求解,通过常微分方程.常微分方程组.高阶常微分方程 3个案例手 ...
- WIN10安装并汉化PLSQL
WIN10安装并汉化PLSQL 安装文件 链接:https://pan.baidu.com/s/12BBEaFQ8G5LztJmCKgnh1w 提取码:96nx 一.安装 1.双击plsqldev.e ...
- FutureTask相关
上周因为项目中的线程池参数设置的不合理,引发了一些问题,看了下代码,发现对JUC中的一些概念需要再清晰些. Runnable @FunctionalInterface public interface ...
- Linux中mail的用法
简介:mail命令是命令行的电子邮件发送和接收工具.操作的界面不像elm或pine那么容易使用,但功能非常完整Red Hat上sendmail服务一般是自动启动的.可以通过下面的命令查看sendmai ...
- 限流神器Sentinel,不了解一下吗?
概述 书接上回:你来说说什么是限流? ,限流的整体概述中,描述了 限流是什么,限流方式和限流的实现.在文章尾部的 分布式限流,没有做过多的介绍,选择了放到这篇文章中.给大伙细细讲解一下 Sentine ...
- jenkins+nexus上传插件发布制品到nexus
nexus安装 nexus安装参考:https://www.cnblogs.com/afei654138148/p/14974124.html nexus配置 创建制品库 制品库URL:http:// ...
- DWORD
C++中使用DWORD不用声明,但是要加头文件Windows.h. DWORD 就是 Double Word, 每个word为2个字节的长度,DWORD 双字即为4个字节,每个字节是8位,共32位. ...