CSP 2022 提高级第一轮 - CSP/S 2022初试题 程序阅读第一题解析

目录

一、代码查看

二、代码分析

三、题目分析


 

阅读程序(程序输入不超过数组或字符串定义的范围;判断题正确填√,错误填×;除特殊说明外,判断题 1.5 分,选择题 3 分,共计 40 分) 

一、代码查看

​
1  #include <iostream> 
2  #include <string> 
3  #include <vector> 
4  
5  using namespace std; 
6  
7  int f(const string &s, const string &t) 
8  { 
9      int n = s.length(), m = t.length(); 
10 
11     vector<int> shift(128, m + 1); 
12 
13     int i, j;
14 
15     for (j = 0; j < m; j++)
16         shift[t[j]] = m - j;
17 
18     for (i = 0; i <= n - m; i += shift[s[i + m]]) {
19         j = 0;
20         while (j < m && s[i +j] == t[j]) j++;
21         if (j == m) return i;
22     }
23 
24     return -1;
25 }
26 
27 int main()
28 {
29     string a, b;
30     cin >> a >> b;
31     cout << f(a, b) << endl;
32     return 0;
33 }

​

二、代码分析

从第18 ~ 22 行代码可以很明显得看出,该题的目的是从s字符串中找出第一个字串t的位置。

for (i = 0; i <= n - m; i += shift[s[i + m]]) {
    j = 0;
    while (j < m && s[i +j] == t[j]) j++;
    if (j == m) return i;
}

j 是 t 串的下标,每次从 0 开始,和 s 串配对,发现不对结束内循环。最后判断 j 是否停留在  t 串的最后一个下标,如果是就说明找到了,便把 i 返回去。

理解了代码的大致意义后,我们从头开始看。

string a, b;
cin >> a >> b;
cout << f(a, b) << endl;

以上是 main() 函数中所做的,意义很简单,就是输入两个字符串 s, t,然后调用 f(s, t) 函数去找字串并输出结果。

接着我们看看 f(s, t) 函数中的内容。

int n = s.length(), m = t.length(); 

这句话将 s 串和 t 串的长度记录在两个变量里。

vector<int> shift(128, m + 1); 
for (j = 0; j < m; j++)
    shift[t[j]] = m - j;

接下来是重点。shift容器中存的是跳过的步数。

3e7fba174fee47e8ab57d2c6bf89e6eb.png

第一次先访问s[0], 从0开始与 t 比较,如果对上了就返回,否则 i 要后移,但是后移几位就要看情况了。为了节省时间,我们要看看 s[i + m]。比如 t = “day”,这个时候我们看看s[i + m]是不是d、a、y中的一个,如果是d,那就从[3]开始,如果是a,那就从[2]开始,如果是y,就从下一个,也就是[1]开始,如果都不是,那就说明近3个不会出答案,那么就+4跳过。

这步看不懂评论区见

 

三、题目分析

判断题

1.(1 分)当输入为“abcde fg”时,输出为-1。(对)【因为abcde中找不到fg】

2.   当输入为“abbababbbab abab”时,输出为 4。(错)【因为字串abab起始位置从0开始,是3】

3.  当输入为“GoodLuckCsp2022 22”时,第 20 行的“j++”语句执行次数为 2。(错)【第一次++是第一个2后,第二次在第二个2后】

单选题

该算法最坏情况下的时间复杂度为(D)。

A. O(n + m)

B. O(n log m)

C. O(m log n)

D. O(nm)

【外循环n内循环m,所以n * m】

f(a, b) 与下列(A)语句的功能最类似

A. a.find(b)

B. a.rfind(b)
C. a.substr(b)
D. a.compare(b)

【.find()函数用于找字串,必须知道,写代码】

当输入为“baaabaaabaaabaaaa aaaa”,第 20 行的“j++”语句执行次数为 (B)。

A. 9

B. 10
C. 11
D. 12

【第一次s[0] = 'b',直接跳过,s[i + 5] = 'a',s[5]~s[7]执行了3次,s[5 + 4] = 'a',执行3次,s[9 + 4] = 'a',执行4次,共10次。

baaabaaabaaabaaaa 标记+过的下标都执行了一次j++

          +++  +++ ++++

 

  • 12
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值