博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【CH1809】匹配统计(KMP)
阅读量:4588 次
发布时间:2019-06-09

本文共 1341 字,大约阅读时间需要 4 分钟。

摘自https://www.cnblogs.com/wyboooo/p/9829517.html

用KMP先求出以a[i]为结尾的前缀与b匹配的最长长度。比如 f[i]  = j,就表示a[1~i]的后缀最多可以和b[1~j]匹配。但求出这个并不意味着以a[i]为开头的后缀可以和b恰好匹配j位(因为也许后面还可以匹配),但是可以肯定的是他至少可以匹配j位。我们很难求出恰好可以匹配x位的位置有多少,但是我们可以存至少可以匹配x位的位置的数目,结果用cnt[x] - cnt[x +1]就可以了。因此cnt[f[i]] ++就很显然了。由于我们之前求出的是最长长度,因此当a[1~i]可以最多和b[1~j]匹配时,也一定存在一个小于j的k使得a[1~i]和b[1~k]匹配,也就是一定能找到一个位置,至少匹配k位,但这个可能我们在之前没有加上过。而这个k恰好就等于nxt[j]。

xjc大佬还提出了一个hash+二分的做法,也能AC。

就是用二分长度+hash check求出每个位置的答案,然后直接用桶记录秒出答案。
时间复杂度\(O(n\log n)\)

#include 
#include
#define Open(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout);const int MAXN = 200010;int nxt[MAXN], n, m, q, f[MAXN], c[MAXN], d;char a[MAXN], b[MAXN];int main(){ Open("str"); scanf("%d%d%d%s%s", &n, &m, &q, a + 1, b + 1); int j = 0; for(int i = 2; i <= m; ++i){ while(j && b[i] != b[j + 1]) j = nxt[j]; if(b[j + 1] == b[i]) ++j; nxt[i] = j; } j = 0; for(int i = 1; i <= n; ++i){ while(j && (a[i] != b[j + 1] || j == m)) j = nxt[j]; if(a[i] == b[j + 1]) ++j; f[i] = j; } for(int i = 1; i <= n; ++i) ++c[f[i]]; for(int i = m; i; --i) c[nxt[i]] += c[i]; for(int i = 1; i <= q; ++i){ scanf("%d", &d); printf("%d\n", c[d] - c[d + 1]); } return 0;}

转载于:https://www.cnblogs.com/Qihoo360/p/11224174.html

你可能感兴趣的文章
数据结构--栈的应用(表达式求值 nyoj 35)
查看>>
注解:大话AOP与Android的爱恨情仇
查看>>
VB调用WebService(SOA2.0接口)(直接Post方式)并解析返回的XML
查看>>
Linux内存管理1---内存寻址
查看>>
java线程详解(三)
查看>>
9.17模拟赛2.0
查看>>
洛谷 P3225 [HNOI2012]矿场搭建
查看>>
orcad找不到dll
查看>>
各种排序算法的性能特点
查看>>
LET IT BE
查看>>
在线帮助你修改图片背景的工具 - Clipping Magic
查看>>
BizTalk动手实验(十三)EDI解决方案开发配置
查看>>
初学github
查看>>
iOS开发拓展篇—UIDynamic(重力行为+碰撞检测)
查看>>
extjs 下载文件 关键前后端代码
查看>>
.NET 4.0 兼容 .NET 2.0 的方法
查看>>
1001 Maximum Multiple(2018 Multi-University Training Contest 1)
查看>>
对Java对象的认识与理解
查看>>
python——父类与子类的一些说明
查看>>
2019年3月3日 2018-2019-2 20189205《移动平台应用开发实践》第二周作业
查看>>