news 2026/8/29 23:05:15

CSP-S 2022 提高级 第一轮 阅读程序(1)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CSP-S 2022 提高级 第一轮 阅读程序(1)

【题目】

CSP-S 2022 提高级 第一轮 阅读程序(1)

01#include<iostream>02#include<string>03#include<vector>0405usingnamespacestd;0607intf(conststring&s,conststring&t)08{09intn=s.length(),m=t.length();1011vector<int>shift(128,m+1);1213inti,j;1415for(j=0;j<m;j++)16shift[t[j]]=m-j;1718for(i=0;i<=n-m;i+=shift[s[i+m]]){19j=0;20while(j<m&&s[i+j]==t[j])j++;21if(j==m)returni;22}2324return-1;25}2627intmain()28{29string a,b;30cin>>a>>b;31cout<<f(a,b)<<endl;32return0;33}

假设输入字符串由 ASCII 可见字符组成,完成下面的判断题和单选题:
判断题
16. 当输入为“abcde fg”时,输出为-1。( )
17. 当输入为“abbababbbab abab”时,输出为 4。( )
18. 当输入为“GoodLuckCsp2022 22”时,第 20 行的“j++”语句执行次数为 2。( )

单选题
19. 该算法最坏情况下的时间复杂度为( )。
A. O(n+m) B. O(n log m) C. O(m log n) D. O(nm)
20. f(a, b)与下列( )语句的功能最类似。
A. a.find(b) B. a.rfind(b) C. a.substr(b) D. a.compare(b)
21. 当输入为“baaabaaabaaabaaaa aaaa”,第 20 行的“j++”语句执行次数为( )。
A. 9 B. 10 C. 11 D. 12

【题目考点】

1. 字符串
  • 字符串模式匹配
2. vector

vector初始化:
vector<元素类型> 对象名(元素个数,初始值)

例:
vector<int> v(10, 3);
生成一个vector<int>类型的对象v,其中包含10个元素,每个元素都是3。也就是说v.size()为10,v[0]~v[9]都是3。

【解题思路】

27intmain()28{29string a,b;30cin>>a>>b;31cout<<f(a,b)<<endl;32return0;33}

先看主函数,输入两个字符串,由f函数处理,输出函数返回的一个什么值。

07intf(conststring&s,conststring&t)08{09intn=s.length(),m=t.length();1011vector<int>shift(128,m+1);

再看函数f,传入两个字符串s,t,先求出字符串长度。s的长度是n,t的长度是m。
而后声明了一个vector,名字叫shift。shift这个词除了由“上档键”的意思,还有“转移,移位”的意思。(其实根据单词可以判断出很多信息,各位同学平时要注意多学习英文单词。)
shift后面的括号中传入两个参数,这是使用了vector的构造函数,传入的第1个参数表明初始化元素的个数,第二个参数是每个元素的值。也就是说,声明出来的shift的长度(元素个数)shift.size()为128,这128个元素,即shift[0]~shift[127]的值都是m+1。至于这个shift是做什么用的,接着往下看。

13inti,j;1415for(j=0;j<m;j++)16shift[t[j]]=m-j;

t[j]是字符,作为shift的下标,也就是以字符的ASCII码为下标,这也对应了shift中要有128个元素。shift的t[j]位置要赋值为m-j,暂时无法理解。如果无法理解就继续向下看,不要纠结于一处,要大处着眼。

18for(i=0;i<=n-m;i+=shift[s[i+m]]){19j=0;20while(j<m&&s[i+j]==t[j])j++;21if(j==m)returni;22}2324return-1;

先看for循环,i从0到n-m,i每次增加shift[s[i + m]]这么一个东西,看不出是什么。
再看循环内部,j从0循环到m-1,每次判断s[i+j]t[j]是否相等。如果看到有不相等的字符,就跳出。如果j遍历到最后,j已经为m,就返回i。
大家应该能看出这一段在做什么(否则就要反思一下自己字符串一节学得如何)这里就是在判断字符串s[i]~s[i+m-1]与字符串t是否相同。如果相同,则返回i。
结合for循环,i从0到n-m,不断比较s[i]~s[i+m-1]与字符串t是否相同,最后一次比较的就应该是s[n-m]~s[n-1]是否与t相同。如果i每次增加1,这就是我们熟悉的判断一个字符串在另一个字符串中出现的位置的代码,也叫字符串的模式匹配。最后的return -1意味着在s中没有找到t,t不是s的子串。
而i每次增加的不是1,而是shift[s[i + m]],显然应该是进行了某种优化。每次i增加1复杂度太高了,可以多加一些,减少循环次数。

结合上面的shift[t[j]] = m-j,以及for循环中的增量表达式i += shift[s[i + m]],i每次增加的量是由s[i+m]决定的。

  • 如果s[i+m]不是t中的字符,那么接下来看的s的子串中只要包含s[i+m],s中的子串与t就一定不能相同(不能匹配)。因此i应该增加m+1,下一次循环从i+m+1开始,看m个字符,看是否与t相同。这也是vector<int> shift(128, m + 1)将shift中元素的初值设为m+1的原因。
  • 如果s[i+m]是t中的字符,那么应该让s[i+m]与t中最后一个该字符对齐,接下来看能否匹配。

s[i+m]为c,字符串t中最后一个字符c出现的下标为j,那么当t[j]s[i+m]对应时,t[0]s[i+m-j]对应,也就是说i应该增加m-j。
再结合

15for(j=0;j<m;j++)16shift[t[j]]=m-j;

以及i += shift[s[i + m]]
可知shift[c]表示当s[i+m]为c时,为了进行下一次有效的匹配,i应该增加的量。
如果t[j]在字符串中重复出现,j更大时shift[t[j]]的值会更新,即shift[c]保存的是字符串t中最后一个c与s[i+m]对应时,i应该增加的量。

整个程序就是优化后的字符串模式匹配,输入字符串a, b

  • 如果b是a的子串,输出b在a中第一次出现的位置
  • 如果b不是a的子串,输出-1。
判断题

16. 当输入为“abcde fg”时,输出为-1。( )
答:T。
fg不是abcde的子串,输出-1,正确。
17. 当输入为“abbababbbab abab”时,输出为 4。( )
答:F。
abab在abbababbbab中第一次出现的位置为3,不是4。错误。
18. 当输入为“GoodLuckCsp2022 22”时,第 20 行的“j++”语句执行次数为 2。( )
答:T。
t字符串为"22",模式串长度m=2
shift['2']=m-j=2-1=1
i为0,s[0]为’G’,‘G’和2不同,s[i+2]为’o’,shift['o']为m+1即3,i增加3
i为3,s[3]为’d’,i增加3。
i为6,s[6]为’c’,i增加3。
i为9,s[9]为’s’,s[i+2]为’2’,shift['2']为1,i增加1。
i为10,s[10]为’p’,s[i+2]为’0’,i增加3。
i为13,s[13]为’2’,执行两次j++后,j==m,直接跳出,返回结果。

单选题

19. 该算法最坏情况下的时间复杂度为( )。
A. O(n+m) B. O(n log m) C. O(m log n) D. O(nm)

答:选D。
比如s是"aaaaaaaa",t是”bbbba”,那么shift['a']为1,i每次增加1,都不能匹配。整体复杂度会退化成没有优化的基本字符串模式匹配。每次匹配都要循环近m次,共进行(n-m)m次,当n >= m时,O((n−m)m)=O(nm)O((n-m)m) = O(nm)O((nm)m)=O(nm)

20. f(a, b)与下列( )语句的功能最类似。
A. a.find(b) B. a.rfind(b) C. a.substr(b) D. a.compare(b)

答:选A。
f函数实现了字符串查找,如果b不是a的子串则返回-1。
string类的成员函数find也实现了相同的功能。
21. 当输入为“baaabaaabaaabaaaa aaaa”,第 20 行的“j++”语句执行次数为( )。
A. 9 B. 10 C. 11 D. 12

答:选B
手动运行,在纸上执行程序。
shift['a']为1。
i为0,baaa中的第一个b与aaaa中的第1个a不同,直接跳过。此时s[i+m]是b,shift['b']为m+1,i直接增加m+1,也就是5。
i为5,指向第2组baaa中的第1个a。匹配3个a,j++执行3次,遇到b与a不相等。此时s[i+m]是a,shift['a']为1,i增加1。
i为6,指向第2组baaa中的第2个a。匹配2个a,j++执行2次,遇到b与a不相等。此时s[i+m]是a,shift['a']为1,i增加1。
i为7,指向第2组baaa中的第3个a。匹配1个a,j++执行1次,遇到b与a不相等。此时s[i+m]是a,shift['a']为1,i增加1。
i为8,指向第3组baaa中的第1个b。此时s[i+m]是b,shift['b']为m+1,i直接增加m+1,变为13。
i为13,执行字符串最后aaaa中的第1个a,与模式串aaaa匹配4个a,j++执行4次。
j++总计执行10次。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/29 23:04:49

牙科AI训练数据集:多类别蛀牙精细分割实战指南

简介&#xff1a;牙齿影像分割是医学图像分析中的基础任务&#xff0c;其核心在于将X光片中不同病理阶段的龋坏区域进行像素级定位与分类。该技术依赖对灰度渐变、解剖边界和伪影干扰的鲁棒建模&#xff0c;关键原理涵盖多类别语义分割、亚像素级掩膜标注及真实临床场景泛化。其…

作者头像 李华
网站建设 2026/8/29 23:01:13

JWT中的Header部分包含哪些信息?

JWT中的Header部分&#xff0c;我们可以把它想象成一张“通行证”的封面或者标题页。这部分主要告诉我们关于这个“通行证”的一些基本情况和制作方式。那么&#xff0c;Header部分通常会包含哪些信息呢&#xff1f;类型&#xff08;Type&#xff09;: 这就像告诉我们这张“通行…

作者头像 李华
网站建设 2026/8/29 23:00:51

商业名册调研参与指南:从材料准备到价值落地

商业之王系列年度名册调研启动的消息&#xff0c;最近在不少创业圈子里传开了。这类年度商业调研评选&#xff0c;表面上是给企业和个人发一个名号&#xff0c;实际上是在做一次行业级的年度价值盘点。如果你正在犹豫要不要参与&#xff0c;或者已经被推荐进入初筛&#xff0c;…

作者头像 李华
网站建设 2026/8/29 22:59:30

编程自学完整指南:Python与C++八个月学习计划

编程自学完整指南&#xff1a;Python与C八个月学习计划 【免费下载链接】cs-self-learning 计算机自学指南 项目地址: https://gitcode.com/GitHub_Trending/cs/cs-self-learning 这篇文章写给没有编程基础、但想认真学会 Python 和 C 的人。它基于开源的计算机自学指南…

作者头像 李华
网站建设 2026/8/29 22:56:06

七天速记前端八股文:高频考点与面试实战策略

“七天速记前端八股文”&#xff0c;这几个字一出来&#xff0c;我就知道屏幕对面大概率是个正在准备跳槽、眼看面试日期逼近&#xff0c;或者刚被简历筛选折磨完、终于拿到一个面试机会的朋友。说实话&#xff0c;前端八股文这几年风评两极分化严重&#xff0c;有人觉得它纯粹…

作者头像 李华
网站建设 2026/8/29 22:55:59

红外狗类目标检测数据集应用指南:从YOLOv8训练到边缘部署

简介&#xff1a;目标检测是计算机视觉的核心任务之一&#xff0c;旨在识别和定位图像中的特定物体。其原理通常基于深度学习模型&#xff0c;通过卷积神经网络提取特征&#xff0c;并利用边界框回归和分类头实现精准定位与识别。这项技术在安防监控、自动驾驶和智能机器人等领…

作者头像 李华