CF 631D KMP运用

KMP自动机详解(CF808G) 啥??kmp还有自动机?? 没错,我们经常听到ac自动机,后缀自动机之类的,kmp自动机我还真是第一次见。。。 前置知识:https://oi-wiki.org/string/kmp/(kmp都不会还学啥kmp自动机) 我接触到这个知识点是由于我碰见了这么一个题目:Codeforces 808G https://codeforces.com/contest/808/problem/G 中文题意在这:https://www.luogu.com.cn/. 阅读详情
D. Messenger
time limit per test
2 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

Each employee of the "Blake Techologies" company uses a special messaging app "Blake Messenger". All the stuff likes this app and uses it constantly. However, some important futures are missing. For example, many users want to be able to search through the message history. It was already announced that the new feature will appear in the nearest update, when developers faced some troubles that only you may help them to solve.

All the messages are represented as a strings consisting of only lowercase English letters. In order to reduce the network load strings are represented in the special compressed form. Compression algorithm works as follows: string is represented as a concatenation of n blocks, each block containing only equal characters. One block may be described as a pair (li, ci), where li is the length of the i-th block and ci is the corresponding letter. Thus, the string s may be written as the sequence of pairs .

Your task is to write the program, that given two compressed string t and s finds all occurrences of s in t. Developers know that there may be many such occurrences, so they only ask you to find the number of them. Note that p is the starting position of some occurrence of s in t if and only if tptp + 1...tp + |s| - 1 = s, where ti is the i-th character of string t.

Note that the way to represent the string in compressed form may not be unique. For example string "aaaa" may be given as , , ...

Input

The first line of the input contains two integers n and m (1 ≤ n, m ≤ 200 000) — the number of blocks in the strings t and s, respectively.

The second line contains the descriptions of n parts of string t in the format "li-ci" (1 ≤ li ≤ 1 000 000) — the length of the i-th part and the corresponding lowercase English letter.

The second line contains the descriptions of m parts of string s in the format "li-ci" (1 ≤ li ≤ 1 000 000) — the length of the i-th part and the corresponding lowercase English letter.

Output

Print a single integer — the number of occurrences of s in t.

Examples
input
5 3
3-a 2-b 4-c 3-a 2-c
2-a 2-b 1-c
output
1
input
6 1
3-a 6-b 7-a 4-c 8-e 2-a
3-a
output
6
input
5 5
1-h 1-e 1-l 1-l 1-o
1-w 1-o 1-r 1-l 1-d
output
0
Note

In the first sample, t = "aaabbccccaaacc", and string s = "aabbc". The only occurrence of string s in string t starts at position p = 2.

In the second sample, t = "aaabbbbbbaaaaaaacccceeeeeeeeaa", and s = "aaa". The occurrences of s in t start at positions p = 1, p = 10, p = 11, p = 12, p = 13 and p = 14.


分析:对模式串和原串进行预处理,因为不可能完全展开进行匹配。连续相同的需要合并,比如3-a 5-a 这样子连续的读入需要合并成一个片段。

如果模式串字符个数为1,那么只要长度足够且字符相同则合法。
如果模式串字符个数为2,那么左右两边长度足够且对应字符相同则合法。
如果模式串字符数大于2,那么需要首尾两个长度足够,并且中间字符串全部想等才合法。

代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long ll;
const int maxn = 2e5+10;
char s[maxn],t[maxn],st[maxn];
ll cnts[maxn],cntt[maxn];
ll Next[maxn];
int n,m;
ll ans;
ll lent,lens;
ll f,e;

void init(){
    ans = 0;
    lent = lens = 0;
    s[0] = t[0] = 0;

    char c[2];
    ll x;
    for (int i=1; i<=n; i++) {
         scanf("%I64d-%s",&x,c);
         if (c[0]==s[lens]) cnts[lens] +=x;
         else {
             cnts[++lens] = x;
             s[lens] = c[0];
         }
    }

    for (int i=1; i<=m; i++) {
         scanf("%I64d-%s",&x,c);
         if (c[0]==t[lent]) cntt[lent] +=x;
         else {
             cntt[++lent] = x;
             t[lent] = c[0];
         }
    }
}

void getnxt(){
    Next[0] = Next[1] = 0;
    ll j = 0;
    for (ll i=2; i<=lent-2; i++) {
        while (j && (st[j+1]!=st[i] || cntt[i]!=cntt[j+1])) j = Next[j];
        if (st[j+1] == st[i] && cntt[i] == cntt[j+1]) j++;
        Next[i] = j;
    }
}

ll kmp(){
   ll sum = 0;
   ll j = 0;
   for (ll i=2; i<lens; i++) {
      while (j && (st[j+1]!=s[i] || cnts[i]!=cntt[j+1])) j = Next[j];
      if (st[j+1] == s[i] && cnts[i] == cntt[j+1]) j++;
      if (j==lent-2){
         if (s[i-(lent-2)]==t[1] && s[i+1]==t[lent] && cnts[i-(lent-2)]>=f && cnts[i+1]>=e) sum++;
         j = Next[j];
      }
   }
   return sum;
}

int main(){
    while (scanf("%d %d",&n,&m)!=EOF){
        init();
        if (lent==1) {
            for (int i=1; i<=lens; i++){
                if (s[i]==t[lent] && cnts[i]>=cntt[lent])
                    ans += cnts[i] - cntt[lent]+1;
            }
        }
        else if (lent==2) {
            for (int i=1; i<lens; i++) {
                if (s[i]==t[1] && s[i+1]==t[2] && cnts[i]>=cntt[1] && cnts[i+1]>=cntt[2]) ans++;
            }
        }
        else {
           strcpy(st+1,t+2);
           st[lent] = 0;
           f = cntt[1] , e = cntt[lent];
           for (int i=1; i<lent; i++) cntt[i] = cntt[i+1];
           getnxt();
           ans = kmp();
        }
        printf("%I64d\n",ans);
    }
    return 0;
}


【信息科学与工程学】【数据科学】数据科学领域 第六篇 算法设计 01 算法设计 阅读详情

相关推荐

MATLAB实战:5步搞定铣削稳定性叶瓣图(附完整代码解析)

本文提供了一份基于MATLAB的铣削稳定性叶瓣图实战指南。通过5个清晰步骤,从动力学原理出发,详细解析了利用半离散法构建稳定性判据、模块化代码设计、高效参数扫描及高级可视化的完整流程,并附有完整代码,帮助工程师快速预测和规避加工颤振,优化铣削工艺参数。

weixin_29197051的博客 194

【题解】【CF631D】Messenger

我们定义S[i]S[i] 代表S的第i块,T[i]T[i] 代表T的第i块。 同时S[l..r]S[l..r] 代表S的l到r位,并且,T[l..r]T[l..r] 代表T的l到r位。 若T是S的字串,则S[l + 1..r - 1]=T[2..m - 1]且S[l].l = T[1].l且S[l].c ≥ T[1].c且S[r].l = T[m].l且S[r].c ≥ T[m].c.

ezoixx130's Blog 3846

数字IC后端设计实现OCC(On-chip Clock Controller)电路介绍及时钟树综合案例

数字IC后端设计实现OCC(On-chip Clock Controller)电路介绍及时钟树综合案例

weixin_37584728的博客 4735

Gym - 101466E ​​​​​​​ Text Editor(KMP求子串出现次数 + 二分大法)

Text Editor One of the most useful tools nowadays are text editors, their use is so important that the Unique Natural Advanced Language (UNAL) organization has studied many of the benefits working wi...

Error Man 的博客 477

匈牙利算法解决指派问题清晰流程

匈牙利算法解决指派问题清晰流程 百度词条上,指派问题(Assignment problem)是这么定义的:在满足特定指派要求条件下,使指派方案总体效果最佳。如:有若干项工作需要分配给若干人(或部门)来完成;有若干项合同需要选择若干个投标者来承包:有若干班级需要安排在若干教室里上课等。   一、做减法(归约): 行归约:每行元素减去该行最小元素。 列归约:每行元素减去该行最小元素。

siss0siss的博客 6万+

Halcon手眼标定实战:从九点标定到机械臂精准抓取(附完整代码)

本文详细介绍了Halcon手眼标定技术在实际工业场景中的应用,重点讲解了九点标定法在机械臂精准抓取中的实现步骤和优化技巧。通过对比Eye-to-Hand和Eye-in-Hand两种模式的特点,提供完整的代码示例和误差分析,帮助工程师快速掌握标定技术,提升自动化系统的精度和稳定性。

weixin_29100927的博客 459

CF346B kmp+dp

这道题应该是比较典型的利用kmp去dp的题目。 我们思考题意他要求我们的子序列不能够和virus串完全匹配,那么我们就可以在原先求最长公共子序列的基础上在加一个维度。就是 f[i][j][z],第一个串枚举到i,第二个串枚举到j,然后他们与virus串匹配的长度是z。 接下来思考转移。 第一个串当做A数组,第二个串当做B数组 即当(A[i] == B[j])的时候可以在原先已经有的子序列基础上加上字符A[i],这个时候与virus匹配到的长度是z。那么这个长度z是由谁转移来的? 这个地方需要kmp去预处理。

塞满箱子的过程 425

报错:subprocess.CalledProcessError: Command ‘[‘where‘, ‘cl‘]‘ returned non-zero exit status 1.

右键此电脑--属性--高级系统设置--环境变量--系统变量--找到Path。Enterprise是企业版,如果你是社区版就找Community。2.安装的时候,c++桌面那个需要勾选。

2301_77554343的博客 1507

周结——(CFdiv 3+ KMP)

这一周做了下学期的第一次CF,做的不是很好,比赛的总结呢 在这儿呢! 就不说了,再说一说这周主要看的一个算法吧! KMP算法 这个算法就是给你两个字符串,让你判断第一个字符串中是否包含第二个字符串。按照常规的方法也能够找,大体思路就是从头开始找,没找到再从第二个开始找,找不到再从第三个开始找~~~~。原本觉得这么算也不是不行,除了比较耗时间以外。但是算法不就是为了简化时间和空间的嘛,况且这个类型的题也做过好多次了所以看见这个算法就马不停蹄的开始涉及了, 算法描述: 这个算法其实是通过找最长公共前后缀,来实现

qq_51769081的博客 341

Ubuntu系统下STM32开发环境搭建:从零配置CubeMX、VSCode与OpenOCD调试实战

本文详细介绍了在Ubuntu系统下搭建STM32开发环境的完整流程,包括CubeMX、VSCode和OpenOCD的安装配置。通过实战教程指导开发者从基础环境准备到工程创建与调试,提供高效的嵌入式开发解决方案,并分享常见问题解决方法。

potato的博客 941

18、近端策略优化(PPO)算法详解

本文详细介绍了近端策略优化(PPO)算法的理论基础、算法流程、实现方法及实际应用。PPO作为当前最受欢迎的策略梯度算法之一,具有易于实现、计算成本低、样本效率高和性能优越等优点。文章对比了基于自适应KL惩罚和基于裁剪目标的两种PPO变体,重点解析了裁剪目标函数的设计原理及其在Actor-Critic框架下的实现方式,并通过Atari Pong游戏展示了完整的训练配置与流程。最后总结了PPO的优势、适用场景及未来发展方向,为强化学习研究者和实践者提供了全面的参考。

mongodb5scout的博客 177

Codeforces Round #344 (Div. 2) D. Messenger CF631D

好久没写KMP 根本想不到这种做法首先先对连续相同的合并一下假设s字符个数为1那么只要长度足够并且字符相同就合法假设s字符个数为2那么左右两边长度都够就可以 但是只有一个位置合法 不能左移或者右移假设s字符个数>=3 那么需要首尾两个长度足够 并且中间的全部相等才行 所以对自身getfail 然后再用t匹配 需要注意首尾的是需要判长度足够就行 所以需要改一下特判#include <ios

sb的博客 582

YOLOv11改进 | Neck篇 | 双向特征金字塔网络BiFPN助力YOLOv11有效涨点

本文给大家带来的改进机制是BiFPN双向特征金字塔网络,其是一种特征融合层的结构,也就是我们本文改进YOLOv11模型中的Neck部分,它的主要思想是通过多层级的特征金字塔和双向信息传递来提高精度。本文给大家带来的结构可以让大家自行调节网络结构大小,同时能够达到一定的轻量化效果,为什么发BiFPN呢因为它算是YOLO系列改进中的常青树了,大家可以借鉴它的双向特征思想来创新自己的Neck结构本文的BiFPN通过yaml文件配置可以让大家自行调配其结构。

Snu77的博客 9098

Codeforces 631D Messenger【KMP】

题意: 给定由字符串块(字符及连续出现的个数)组成的字符串t,s,求t串中有多少个s。 分析: KMP 这题唯一需要思考的地方就是如何处理字符串块。第一想到是把他们都展开然后进行KMP,可是展开后实在太长,所以必须按块进行处理,就要把所有相邻的相同的块进行合并成一个大块。 注意模式串开头和结尾处与t中对应的块不需要严格相等,只要字符相同并且t中个数不小于模式...

An55511的博客 206

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

[KMP] Codeforces #631D. Messenger

首先要把相同的缩到一起,然后考虑就是一个简单的匹配。 注意到b串两端的字符在a串里匹配可能比a串里那一块少。解决办法就是先把b的两端扣掉匹配,每次匹配成功时判断一下就好了。#include<cstdio> #include<algorithm> #define Fir first #define Sec second #define mp(x,y) make_pair(x,y) using nam

Lynstery's blog 454

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

codeforces 631D Messenger - KMP算法

传送门 题解:模板题,分类讨论。 #include #include #include #define N 1000010 #define lint long long using namespace std; int nxt[N],pos[N];lint cs[N],ct[N]; char s[N],t[N]; inline int get_nxt(char *s,lint *c,int

Mys_C_K的博客 451

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

codeforces 631d D. Messenger

题意:就是找第二个串在第一个串中出现的次数。 思路:kmp  对于如果T串只有1个或者两个字符就可以直接暴力了。但是对于有三个的字符就不可以了。那么把问题转化一下,就是去掉T串的首字符和尾字符,那么肯定其他的字符一定是相等的并且个数相等,那么我就直接kmp找出去掉首尾后在S中出现的个数,并记录下标,那么就可以最后再judge一下S中的首尾是否大于等于T中的首尾。kmp理解不到位就被kmp耍成傻逼...

yjt9299的博客 435

CF 149E Martian Strings(KMP)

转载请注明出处,谢谢http://blog.youkuaiyun.com/ACM_cxlove?viewmode=contents    by---cxlove   题意:给了一个母串,然后有多个匹配串,问在母串中是否能找到不重叠两个子串,拼接成匹配串 http://codeforces.com/problemset/problem/149/E   我的做法是,对于每一个匹配串 正向KMP一次,记

窝不是爱酱,喵~~~~ 1986

CodeForces - 631D Messenger —— kmp思维

D. Messenger time limit per test 2 seconds memory limit per test 512 megabytes input standard input output standard output Each employee of the "Blake Techologies" company uses a special mes...

Lngxling的博客 479

cf432 D (kmp-ekmp)

公开20190809博客,汗 http://codeforces.com/contest/432/problem/D ekmp模板题 此题kmp做法: ac代码: #include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + 5; typedef long long ll; int ans[maxn]...

zlkqlyc的博客 241

CF 432D(kmp)

D. Prefixes and Suffixes time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output You have a strings = s1s2......

weixin_30315723的博客 154

CF 631C

题目:对n&lt;200000的数组,给出m种从1开始到r为止的升序或降序排序,m&lt;200000,求最终输出序列题解:1. 不管前面排了多少次小区间,只要在后面排了一次大区间,结果只受最后一次排序影响。所以维护单调队列。2. 前面是大区间,后面是小区间,只有当排序方式不同时才需要重新排序。3. 第一次排序过后剩下的排序等价于翻转。好这样就有了O(N2)的算法,暴力一波看看数据水不水。……那再...

mengwuyaaa的博客 763

Codeforces Round #344 (Div. 2)D. Messenger【kmp】

D. Messenger time limit per test 2 seconds memory limit per test 512 megabytes input standard input output standard output Each employee of the "Blake Techologies" compa

走一步再走一步 649

CF 126B Password (KMP,利用next数组)

链接: http://www.codeforces.com/problemset/problem/126/B 题目大意: 给定一个字符串S, 找到一个子串t,使得这个子串既和S的前缀相同,又和S的后缀相同,但是t不能是S的前缀或后缀。 分析与总结: 利用和理解next数组的好题,首先可以找到所有与前缀相同的后缀的长度, 另len=|S|, 那么next[len] 就是

D_Double's Journey 1821

Codeforces Round #344 (Div. 2) D. Messenger kmp

D. Messenger 题目连接: http://www.codeforces.com/contest/631/problem/D Description Each employee of the "Blake Techologies" company uses a special messaging app "Blake Messenger". All the stuff likes this...

weixin_34200628的博客 136
上一篇: CF126B KMP算法运用
下一篇: CF 454B Little Pony and Sort by Shift KMP算法简单运用
罗侯
博客等级 码龄10年 135粉丝 258原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值