[导读]:超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成,后续会不定期解读蓝桥杯真题,这是Scratch蓝桥杯真题解析第158讲。
第15届蓝桥第2次STEMA测评已于2023年10月29日落下帷幕,编程题一共有6题,分别如下:
旅游相册
隐身的小鸟
摩天轮
找不同游戏
字母不重复的子串
卡片排列
字母不重复的子串,本题是2023年10月29日举行的第15届蓝桥STEMA测评Scratch编程初/中级组编程第5题,题目要求编程找出给定字符串中字母不重复的子串。
先来看看题目的要求吧。
背景信息:
子串为一个字符串的一段连续的部分。
例如:
字符串为abbcd
abbcd的子串有:a、ab、abb、abbc、abbcd、b、bb、bbc、bbcd、 bc、 bcd、c、cd、d
其中,子母不重复的子串有:a、ab、b、bc.、bcd、c、cd、d
编程实现:
字母不重复的子串。
具体要求:
1). 点击绿旗,角色、背景如图所示(列表“子串”为空);
2). 鼠标点击机器人后,机器人询问“请输入一串小写字母”,如图所示;
3). 输入完成后,列表中出现字母不重复的所有子串;
例如:输入为abbcd
4). 最后,机器人说出列表中最长子串的长度,如图所示;
评判标准:
10分:满足"具体要求"中的1);
5分:满足"具体要求"中的2);
40分:满足"具体要求"中的3);
25分:满足"具体要求"中的4)。
本题只有1个角色,就是机器人,如图所示:
机器人也没有什么特别的动作,就是将玩家输入的字符串进行处理,得到相应的结果。
我们可以将本题归入算法题,考查的是字符串和列表的相关运算及灵活运用。
根据题目的描述,我们可以把字符串的处理拆分成如下3个过程:
获取所有的子串
去重处理
计算最长子串长度
为了更好地理解这3个过程,超平老师以本题的输入样例来说明,即输入的字符串是abbcd。
1. 第一步,获取所有的子串
即获取a、ab、abb、abbc、abbcd、b、bb、bbc、bbcd、 bc、 bcd、c、cd、d等子串,一共有14个。
要获取所有的子串,需要用到循环,而且是嵌套循环,我们可以使用表格将这个过程绘制出来。
字符串abbcd的长度为5,一共需要循环5次。
第1次循环,从第1个字符a开始,获取所有的子串,包括a、ab、abb、abbc、abbcd,一共5个,存入列表。
第2次循环,从第2个字符b开始,获取所有的子串,包括b、bb、bbc、bbcd,一共有4个,存入列表。
第3次循环,从第3个字符b开始,获取所有的子串,包括b、bc、 bcd,一共有3个,存入列表。
第4次循环,从第4个字符c开始,获取所有的子串,包括c、cd,一共有两个,存入列表。
第5次循环,从第5个字符d开始,获取所有的子串,包括d,一共有1个,存入列表。
按照上面的过程,存入列表的子串一共有 5 + 4 + 3 + 2 + 1 = 15个,但实际上只有14个,哪里不对劲呢?
聪明的你肯定已经发现了,这里有两个子串b,所以如果两个字符串完全相同,在存入列表的时候只能添加一次。
2. 第二步 ,去重处理
上面的字符串中,有些组合是有相同的字母,比如abb、abbc、bb等,需要将这些字符串过滤掉,最后得到8个子串,a、ab、b、bc.、bcd、c、cd、d。
去重的思路很简单,就是对于一个给定的字符串,只需要判断其中是否有相同字母即可,具体怎么判断呢?
我们可以借助一个临时列表,对字符串进行遍历,每次获取一个字母,如果临时列表中包含它,就说明有重复字母,否则就将其添加到临时列表中。
3. 第三步,计算最长子串长度
在第二步的基础上,计算最长子串的长度,很显然,在上面的8个子串中,bcd是最长的子串,其长度为3。
这一步比较简单,增加一个变量“最大长度”,先将其设为0,在插入列表的时候,逐个判断,如果当前子串的长度大于最大长度,则更新最大长度的值。
思路有了,接下来,我们就进入具体的编程实现环节。
根据上面的思路分析,我们分4步来编写程序:
准备工作
获取所有子串
去重处理
计算最长子串长度
1. 准备工作
创建好列表“子串”和变量“最大长度”,在机器人角色中编写代码如下:
2. 获取所有子串
点击角色,出现询问框,当输入一串小写字母,根据前面的思路分析,需要使用嵌套循环,将子串组合起来,添加到列表中。
在机器人角色中编写代码如下:
代码有点多,说明如下:
1). 这是一个典型的两层嵌套循环,外层的循环次数通过变量"i"来控制,内层的循环次数通过变量"j"来控制,在编程中,通常将这样的变量称作计数器;
2). 每次需要获得一个子字符串,这里的变量“字符串”,用来表示一个子串, 每次都将其初始值设置为空;
3). 子串组合的过程其实就是字符串的拼接,会用到字符串连接运算符;
4). 每得到一个子字符串,就将其添加到列表中;
5). 不要忘了计数器变量"i"和"j"增加1;
可以先测试一下效果,结果如下:
很显然,这里有两个相同的子串b,没有进行过滤,所以在插入列表的时候,需要增加一个判断,只有当列表中没有该子串时才能插入,代码如下:
如此一来,就可以确保没有相同的子串了。
3. 去重处理
根据前面的思路分析,我们可以借助一个临时列表来去重,先创建好“临时列表”,对于给定的一个字符串,需要判断是否有相同字母。
为了方便,我们可以使用自制积木来实现这一功能,然后使用全局变量"flag"来表示是否有重复字母,flag = 1表示没有重复字母,flag = 0则表示有重复字母。
自制积木的代码如下:
代码较多,说明如下:
1). 先将flag设置为1,假设字符串str是不重复的;
2). 如果字符串长度为1,肯定不会重复,直接结束自制积木脚本 ;
3). 使用循环对字符串进行遍历,如果当前字符在列表中,说明重复了,将flag设置为0,然后结束脚本,否则就将其插入到临时列表中。
有了这个自制积木,就可以在插入列表之前进行判断了,在前面的代码中,增加判断如下:
这样一来,就可以将有相同字母的子串过滤掉了。
4. 计算最长子串长度
这一步比较简单,对每个插入列表的字符串进行比较更新即可,继续增加代码如下:
有两点需要注意:
1). 变量”最大长度“需要初始化为0,通常是在绿旗指令中;
2). 在循环完成之后,使用说话指令说出最大长度。
至此,整个作品就创作好了,你可以输入各种形式的字符串来测试效果啦。
本题是中级组编程部分第5题,分数为80分,积木块数量70个左右,涉及到的知识点主要包括:
Scratch问答指令;
循环编程,尤其是嵌套循环;
条件编程,包括单分支和多分支;
变量的使用;
列表的基本操作;
字符串连接运算;
自制积木;
本题难度较大,难点有两个,一是如何使用嵌套循环获取所有的子串,二是如何对字符串进行去重处理。
获取所有的子串,实际上就是数学中的排列组合问题,在小学数学中有一类非常经典的”打枪法“数线段题目,和本题的做法是一样的,其本质是枚举算法,就是把所有的情况都列举出来。
至于去重处理,在编程中十分常见,最基本的方法就是借助列表(或集合)来实现,只要知道其原理,代码倒不难。
关键是如何组织代码,去重是一个独立的功能,此时我们应该想到函数的编程思想,将其定义成自制积木,从而简化代码结构。
你还有什么好的思路和方法吗,也欢迎和超平老师交流。
如果你觉得文章对你有帮助,别忘了点赞和转发,予人玫瑰,手有余香
需要素材和源码的,可以移步至“超平的编程课”gzh。