CCF CSP认证历年题目自练Day38

题目

试题编号: 201409-3
试题名称: 字符串匹配
时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  给出一个字符串和多行文字,在这些文字中找到字符串出现的那些行。你的程序还需支持大小写敏感选项:当选项打开时,表示同一个字母的大写和小写看作不同的字符;当选项关闭时,表示同一个字母的大写和小写看作相同的字符。
输入格式
  输入的第一行包含一个字符串S,由大小写英文字母组成。
  第二行包含一个数字,表示大小写敏感的选项,当数字为0时表示大小写不敏感,当数字为1时表示大小写敏感。
  第三行包含一个整数n,表示给出的文字的行数。
  接下来n行,每行包含一个字符串,字符串由大小写英文字母组成,不含空格和其他字符。
输出格式
  输出多行,每行包含一个字符串,按出现的顺序依次给出那些包含了字符串S的行。
样例输入
Hello
1
5
HelloWorld
HiHiHelloHiHi
GrepIsAGreatTool
HELLO
HELLOisNOTHello
样例输出
HelloWorld
HiHiHelloHiHi
HELLOisNOTHello
样例说明
  在上面的样例中,第四个字符串虽然也是Hello,但是大小写不正确。如果将输入的第二行改为0,则第四个字符串应该输出。
评测用例规模与约定
  1<=n<=100,每个字符串的长度不超过100。

题目分析(个人理解)

  1. 其实,这题目就告诉我们要考什么内容了,对于字符串的匹配有两种算法,第一种,BF算法,也就是朴素算法。还有一种,KMP算法。
  2. 由于测试长度较小,可以遍历比较,也就是BF算法足以。可以利用python的.find()方法实现查找,该函数会返回模式串第一个字符在母串的位置,如果不存在则返回-1。第一行输入的是模式串,第二行输入开关(1就是区分大小写,0不区分),第三行输入有n个母串,之后的n行输入n个母串,如果不区分大小写,可将母串与模式串都转化成大写或小写,然后判断是否匹配即可(使用.upper()方法可将字符串小写字母全部转为大写)。如果区分大小写,单用find()方法,判断是否存在即可。
  3. 最后输出存在的匹配的母串即可,上代码!!!
#朴素算法
s=input().strip()
m=int(input())
n=int(input())
for i in range(n):#枚举每一个字母,扫描每一个位置并且判断是否匹配x=input().strip()if m==1 :if x.find(s)!=-1:print(x)else:if x.upper().find(s.upper())!=-1:print(x)
  1. 模式匹配问题:就是在一篇长度为n的文本S中,查找某个长度为m的关键词P,称S为母串,P为模式串。P可能出现多次,都需要找到。
  2. BF算法是一种暴力解法,复杂度至少O(m+n),从S的第一个字符开始,逐个匹配P的每一个字符,如果发现不同就从S的下一个字符重新开始匹配。暴力方法哪里不好?遇到恶劣一点的模式串,如果模式串在匹配的时候一直到最后一个字符才匹配失败,那复杂度直接退化成O(nm)。所以说这种算法很不稳定。之后进化出了KMP算法。
  3. KMP算法是一种在任何情况下都可以达到O(m+n)复杂度的算法。我在介绍朴素算法的时候,,就是在匹配失败的时候指向P的指针j都要回溯到0,也就是又要从模式串第一个开始匹配,指向S的指针i都要回溯,这也就是弊端。
  4. 对于字符串的样子在匹配的时候可以分类,第一类,P在失配点之前的每个字符都不相同,在这种情况下可以直接把P滑动到S的i位置,此时i不变,j回溯到0,然后直接下一步匹配。第二类,P在失配点之前的字符有部分相同,关键是相同的部分在哪里,这又可以分为两种情况,相同的部分是前缀(在P的最前面)和后缀。假如在i号位失配,前缀与后缀相同时可以将P的前缀的后一位滑动到S的i号位做比较即可。第二种情况,相同的部分不是前缀或后缀,那只能按照第一类去判断,j回溯到i的位置在做匹配的判断。
  5. 好了,根据第七点我的解释,现在我们只需要找到最长公共前后缀和,也就是出现第二类的第一种情况的时候如何解决,第一类和第二类的第二种情况当匹配失败的时候只需要将j回溯到i即可。完全不需要回溯i,关键在于计算p的前缀和后缀。
  6. Next[]数组的计算:例:P = “abcaab”,计算过程如下表,每一行的下划线串是最长公共前后缀。在这里插入图片描述
    计算Next[]:复杂度O(m)的方法,利用前缀和后缀的关系,从Next[i]递推到Next[i+1]。
    假设已经算出Next[i],它对应P[0]~P[i-1]这部分子串的后缀和前缀。
    阴影部分w是最长交集,交集w的长度等于Next[i]。
    上半部分的阴影所示的后缀的最后一个字符是P[i-1];
    下半部分阴影所示前缀的第一个字符是P[0],最后一个字符是P[j],j = Next[i]-1。

在这里插入图片描述
推广到Next[i+1],它对应P[0]~P[i]的后缀和前缀。
此时后缀的最后一个字符是P[i],与这个字符相对应,把前缀的j也往后移一个字符,j = Next[i]。判断两种情况:
(1)若P[i] = P[j],则新的交集等于“阴影w+ P[i]”,交集的长度Next[i+1] = Next[i]+1。
在这里插入图片描述
2)若P[i] ≠ P[j],说明后缀的“阴影w+P[i]”与前缀的“阴影w+P[j]”不匹配,只能缩小范围找新的交集。

在这里插入图片描述

下图合并了前缀和后缀,画出完整的子串P[0]~P[i],最后的字符P[i]和P[j]不等。
在这里插入图片描述
在这里插入图片描述
把前缀往后滑动,也就是通过减小j来缩小前缀的范围,直到找到一个匹配的P[i] = P[j]为止。
如何减小j?只能在w上继续找最大交集,这个新的最大交集是Next[j],所以更新j’ = Next[j]。
下图斜线阴影v是w上的最大交集,下一步判断:

若P[i] = P[j’],则Next[i+1]等于v的长度加1,即Next[j’]+1;
若P[i] ≠ P[j’],继续更新j’。

在这里插入图片描述
10. KMP算法代码如下!!!

N=1000005
Next = [0]*N
def getNext(p):                      #计算Next[1]~Next[plen]for i in range(1,len(p)):j = Next[i];                 #j的后移:j指向前缀阴影w的后一个字符while j>0 and p[i] != p[j]:  #阴影的后一个字符不相同j = Next[j]              #更新jif p[i]==p[j]:   Next[i+1] = j+1else:             Next[i+1] = 0
def kmp(s,p):ans = 0j = 0for i in range(0,len(s)):        #S的i指针,它不回溯,用for循环一直往前走。
#匹配S和P的每个字符                             while j>0 and s[i]!=p[j]:    #失配了j=Next[j]               #j滑动到Next[j]位置if s[i]==p[j]:               #若s[i]==p[j],说明当前P的字符和S的字符匹配j++,
#同时回到13行i++
#下一步匹配s[i+1]和p[j+1]。
#当前位置的字符匹配,继续j+=1ans = max(ans,j)          if j == len(p): return ans   #最长前缀就是p的长度,直接返回                       return ans                       #返回p在s中出现的最长前缀
s=input()
t=input()  
getNext(t)
print(kmp(s,t))
  1. 本题用kmp算法实现如下!!!
#KMP算法实现
def find(x):j=0for i in range(len(x)):while j!=0 and s[j]!=x[i]:j=p[j]if s[j]==x[i]:j=j+1if j==len(s):return 1return -1
s=input().strip()
m=int(input())
n=int(input())
if m==0:s=s.upper()
#计算kmp算法的next数组,这里我叫p
p=[0 for _ in range(len(s)+1)]
p[1]=0
j=0
for i in range(1,len(s)):while j != 0 and s[j] != s[i]:j = p[j]if s[j] == s[i]:j = j + 1p[i]=j
for i in range(n):x=input().strip()#枚举每一个母串,一次扫描if m==1:if find(x)!=-1:print(x)else:if find(x.upper())!=-1:print(x)

总结

程序员节快乐!!!
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/168771.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

酒类商城小程序怎么做

随着互联网的快速发展&#xff0c;线上购物越来越普及。酒类商品也慢慢转向线上销售&#xff0c;如何搭建一个属于自己的酒类小程序商城呢&#xff1f;下面就让我们一起来看看吧&#xff01; 一、登录乔拓云平台 首先&#xff0c;我们需要进入乔拓云平台的后台&#xff0c;点击…

《向量数据库》——Zilliz X Dify.AI ,快速打造知识库 AI 应用

Zilliz 大模型生态矩阵再迎新伙伴!近日,Zilliz 和 Dify.AI 达成合作,Zilliz 旗下的产品 Zilliz Cloud、Milvus 与开源 LLMOps 平台 Dify 社区版进行了深度集成。 01. Zilliz Cloud v.s. Dify Dify 作为开源的 LLMs App 技术栈,在此前已支持丰富多元的大型语言模型的接入,…

【React Router】React Router学习笔记

React Router学习笔记 React Router1.什么是React Router?2.为什么要用React Router?3.基础3.1 路由配置3.2 路由匹配原理3.3 History3.3.1 browerHistory3.3.2 hashHistory3.3.3 createMemoryHistory3.3.4 实现示例 3.4 默认路由(IndexRoute)与IndexLink3.4.1 IndexRoute3.4…

[SQL开发笔记]WHERE子句 : 用于提取满足指定条件的记录

SELECT DISTINCT语句用户返回列表的唯一值&#xff1a;这是一个很特定的条件&#xff0c;假设我需要考虑很多中限制条件进行查询呢&#xff1f;这时我们就可以使用WHERE子句进行条件的限定 一、功能描述&#xff1a; WHERE子句用于提取满足指定条件的记录&#xff1b; 二、WH…

报错解决:libcudart.so和libprotobuf.so链接库未找到

报错解决&#xff1a;libcudart.so和libprotobuf.so链接库未找到 libcudart.so链接库未找到原因解决方法 libprotobuf.so链接库未找到原因解决方法 此博客介绍了博主在编译软件包时遇到的两个报错&#xff0c;主要是libcudart和libprotobuf两个动态链接库未找到的问题&#xff…

Nginx安装配置项目部署然后加SSL

个人操作笔记记录 第一步&#xff1a;把 nginx 的源码包nginx-1.8.0.tar.gz上传到 linux 系统 第二步&#xff1a;解压缩 tar zxvf nginx-1.8.0.tar.gz 第三步&#xff1a;进入nginx-1.8.0目录 使用 configure 命令创建一 makeFile 文件。 直接复制过去运行 ./configur…

【RocketMQ系列十二】RocketMQ集群核心概念之主从复制生产者负载均衡策略消费者负载均衡策略

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精…

KingBase库模式表空间和客户端认证(kylin)

库、模式、表空间 数据库 数据库基集簇与数据库实例 KES集簇是由单个KES实例管理的数据库的集合KES集簇中的库使用相同的全局配置文件和监听端口、共享相关的进程和内存结构同一数据库集簇中的进程、相关的内存结构统称为实例 数据库 数据库是一个长期存储在计算机内的、有…

【Tensorflow 2.12 简单智能商城商品推荐系统搭建】

Tensorflow 2.12 简单智能商城商品推荐系统搭建 前言架构数据召回排序部署调用结尾 前言 基于 Tensorflow 2.12 搭建一个简单的智能商城商品推荐系统demo~ 主要包含6个部分&#xff0c;首先是简单介绍系统架构&#xff0c;接着是训练数据收集、处理&#xff0c;然后是召回模型、…

redis分布式锁的应用

redis 作为分布式锁的东西 分布式锁的应用 redis,zk,数据库这些都可以实现分布式锁 我们今天主要基于redis实现的分布式锁&#xff0c;而且要求性能要好 基于一个小的业务场景来说&#xff0c;就比如说秒杀中的减库存&#xff0c;防止超卖这种代码就会有并发问题,比方说3个线程…

uni-app开发

uni-app 官方手册&#xff1a;uni-app官网 一&#xff1a;tarBar&#xff1a;一级导航栏&#xff0c;即 tab 切换时显示对应页。 在pages.json文件里写入如下代码&#xff1a; 此效果&#xff1a;

编译工具链 之一 基本概念、组成部分、编译过程、命名规则

编译工具链将程序源代码翻译成可以在计算机上运行的可执行程序。编译过程是由一系列的步骤组成的&#xff0c;每一个步骤都有一个对应的工具。这些工具紧密地工作在一起&#xff0c;前一个工具的输出是后一个工具的输入&#xff0c;像一根链条一样&#xff0c;我们称这一系列工…

Unity 单例-接口模式

单例-接口模式 使用接口方式实现的单例可以继承其它类&#xff0c;更加方便 using System.Collections; using System.Collections.Generic; using UniRx; using UniRx.Triggers; using UnityEngine; namespace ZYF {public interface ISingleton<TMono> where TMono : M…

力扣第55题 跳跃游戏 c++ 贪心 + 覆盖 加暴力超时参考

题目 55. 跳跃游戏 中等 相关标签 贪心 数组 动态规划 给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回 true &…

Unity编辑器扩展 --- AssetPostprocessor资源导入自动设置

unity导入资源的编辑器设置: 防止策划资源乱导入,资源导入需要的格式&#xff0c;统一资源管理 AssetPostprocessor资源导入管线 AssetPostprocessor用于在资源导入时自动做一些设置&#xff0c;比如当导入大量图片时&#xff0c;自动设置图片的类型&#xff0c;大小等。Ass…

AlDente Pro for Mac: 掌控电池充电的终极解决方案

你是否曾经为了保护你的MacBook的电池&#xff0c;而苦恼于无法控制它的充电速度&#xff1f;AlDente Pro for Mac 是一款专为Mac用户设计的电池管理工具&#xff0c;它能帮助你解决这个问题。 AlDente Pro for Mac 是一款电池最大充电限制软件&#xff0c;它能够让你自由地设…

【数据结构与算法】二叉树的运用要点

目录 一&#xff0c;二叉树的结构深入认识 二&#xff0c;二叉树的遍历 三&#xff0c;二叉树的基本运算 3-1&#xff0c;计算二叉树的大小 3-2&#xff0c;统计二叉树叶子结点个数 3-3&#xff0c;计算第k层的节点个数 3-4&#xff0c;查找指定值的结点 一&#xff0c;二叉…

ResNet论文精读,代码实现与拓展知识

文章目录 ResNet 论文精读代码实现网络可视化代码 拓展知识 ResNets残差的调参残差链接的渊源残差链接有效性的解释ResNet 深度ResNeXt代码实现 能够提点的技巧「Warmup」「Label-smoothing」「Random image cropping and patching」「Knowledge Distiallation」「Cutout」「Ra…

Centos 7 Zabbix配置安装

前言 Zabbix是一款开源的网络监控和管理软件&#xff0c;具有高度的可扩展性和灵活性。它可以监控各种网络设备、服务器、虚拟机以及应用程序等&#xff0c;收集并分析性能指标&#xff0c;并发送警报和报告。Zabbix具有以下特点&#xff1a; 1. 支持多种监控方式&#xff1a;可…

SAP POorPI RFC接口字段调整后需要的操作-针对SP24及以后的PO系统

文章目录 问题描述解决办法 问题描述 在SAP系统的RFC接口结构中添加了字段&#xff0c;RFC也重新引用到了PO系统&#xff0c;Cache和CommunicationChannel都刷新或启停了&#xff0c;但是新增的字段在调用接口的时候数据进不到SAP系统&#xff0c;SAP系统内的值也出不来。经过…