CSP-J 2023 入门级 第一轮 阅读程序(2)

【题目】

CSP-J 2023 入门级 第一轮 阅读程序(2)

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int f(string x, string y) {
    int m = x.size();
    int n = y.size();
    vector<vector<int>> v(m + 1, vector<int>(n + 1, 0));
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            if (x[i - 1] == y[j - 1]) {
                v[i][j] = v[i - 1][j - 1] + 1;
            } else {
                v[i][j] = max(v[i - 1][j], v[i][j - 1]);
            }
        }
    }
    return v[m][n];
}
bool g(string x, string y) {
    if (x.size() != y.size()) {
        return false;
    }
    return f(x + x, y) == y.size();
}
int main() {
    string x, y;
    cin >> x >> y;
    cout << g(x, y) << endl;
    return 0;
}

判断题
21. f函数的返回值小于等于min(n,m)。( )
22. f函数的返回值等于两个输入字符串的最长公共子串的长度。( )
23. 当输入两个完全相同的字符串时,g函数的返回值总是true( )
单选题
24. 将第19行中的"v[m][n]“替换为"v[n][m]”,那么该程序( )
A. 行为不变 B. 只会改变输出 C. 一定非正常退出 D. 可能非正常退出
25. 当输入为"csp-j p-jcs"时,输出为()
A. “0” B. “1” C. “T” D. “F”
26. 当输入为"csppsc spsccp"时,输出为:()
A. “T” B. “F” C. “0” D. “1”

【题目考点】

1. 线性动态规划

求最长公共子序列
参考:信息学奥赛一本通 1265:【例9.9】最长公共子序列

2. vector

vector是顺序存储结构的线性表(顺序表),可以将其视为长度可变的数组。
声明vector对象:
vector<数据类型> 对象名;

例:声明保存int类型的顺序表v:vector<int> v;

使用构造函数:
vector<数据类型> 对象名(线性表长度);

例:声明保存int类型的顺序表v,线性表长度为10(即包含v[0]~v[9]共10个元素,初值为0):vector<int> v(10);

vector<数据类型> 对象名(线性表长度, 元素初值);

例:声明保存int类型的顺序表v,线性表长度为10,元素初值为1。(即包含v[0]~v[9]共10个元素,每个元素初值为1):vector<int> v(10, 1);

【解题思路】

先看f函数

int f(string x, string y) {
    int m = x.size();
    int n = y.size();

传入两个字符串x和y,m是字符串x的长度(字符个数),n是字符串y的长度。

vector<vector<int>> v(m + 1, vector<int>(n + 1, 0));

vector<int>(n + 1, 0)表示声明一个保存int类型变量的vector,长度是n+1(这个vector中有n+1个元素),元素初值为0。
vector<vector<int>>表示外层vector中每个元素都是vector<int>类型的对象。
v(m+1, vector<int>(n+1, 0))表示外层vector对象名是v,长度是m+1,每个元素的初值都是vector<int>(n+1, 0)
外层顺序表中有m+1个元素,每个元素都是一个保存int类型的长度为n+1的顺序表。
实际这一段就是在使用vector声明一个m+1行n+1列的二维数组v。

    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            if (x[i - 1] == y[j - 1]) {
                v[i][j] = v[i - 1][j - 1] + 1;
            } else {
                v[i][j] = max(v[i - 1][j], v[i][j - 1]);
            }
        }
    }
    return v[m][n];
}

这一段必须先学过线性动规中的求最长公共子序列问题后才可以理解。如对该问题不清楚,详见:(信息学奥赛一本通 1265:【例9.9】最长公共子序列)
这段代码中,v[i][j]是状态,表示x字符串的前i个字符和y字符串的前j个字符的最长公共子序列的长度。
最后返回v[m][n],即x字符串的前m个字符和y字符串的前n个字符的最长公共子序列的长度。
因此,int f(string x, string y)求的就是x字符串和y字符串的最长公共子序列的长度。

bool g(string x, string y) {
    if (x.size() != y.size()) {
        return false;
    }
    return f(x + x, y) == y.size();
}

g函数传入两个字符串x,y。

  • 如果两字符串长度不同,则返回false。
  • 如果长度相同,先求x+x(x后面再连接x得到的字符串)和y字符串的最长公共子序列的长度,看该长度是否与y的长度相同。也就是看x+x中是否存在一个子序列是y字符串。(在x+x中顺序选取部分字符(可以跳着选),看能否选出完整的y字符串)。
int main() {
    string x, y;
    cin >> x >> y;
    cout << g(x, y) << endl;
    return 0;
}

主函数,输入x,y字符串,输出x+x是否存在一个子序列是y字符串,如果存在输出1,否则输出0。

判断题
21. f函数的返回值小于等于min(n,m)。( )

答:T
f函数求x与y的最长公共子序列的长度,两字符串最长公共子序列的长度不会大于两字符串中任意一个字符串,最长时也就是与两字符串中更短的字符串一样长。该判断正确。

  1. f函数的返回值等于两个输入字符串的最长公共子串的长度。( )

答:F
f函数的返回值是两个输出字符串的最长公共子序列的长度,而不是最长公共子串。子串是连续元素构成的子序列。子序列可以是不连续的,子串必须是连续的。
比如bcdabcde的子串,也是子序列。而aceabcde的子序列,不是子串。

  1. 当输入两个完全相同的字符串时,g函数的返回值总是true( )

答:T
当x与y相同时,x+x中一定存在子串y(即子串x),子串就是子序列,所以x+x与y的最长公共子序列的长度就是y的长度,g函数返回真。

单选题
24. 将第19行中的"v[m][n]“替换为"v[n][m]”,那么该程序( )
A. 行为不变 B. 只会改变输出 C. 一定非正常退出 D. 可能非正常退出

答:D
如果输入的x与y长度不等,那么不会运行到f函数,直接输出0,没有非正常退出。
如果输入的x与y长度相等(空字符串无法输入,字符串长度最小为1),在g函数中调用的是f(x+x, y),运行到函数内部,int f(string x, string y),形参x的长度一定是y的二倍。也就是m == 2*n,因此也一定有m > n。
把v当做二维数组,v的第一维的长度是m+1,可以使用的下标范围是0~m。第二维的长度是n+1,可以使用的下标范围是0~n。由于m>n,当取v[n][m]时第二维数组越界,会产生运行时错误。(出现运行时错误时,程序可能会正常退出,也可能非正常退出。我们应该默认它会非正常退出。)

  1. 当输入为"csp-j p-jcs"时,输出为()
    A. “0” B. “1” C. “T” D. “F”

答:B
看csp-jcsp-j中是否存在子序列是p-jcs。
仔细看,是存在的。csp-jcsp-j。
第3到第7字符就是p-jcs。
输出1。(输出布尔值真时,输出1,输出布尔值假时,输出0)

  1. 当输入为"csppsc spsccp"时,输出为:()
    A. “T” B. “F” C. “0” D. “1”

答:D
看csppsccsppsc中是否存在子序列是spsccp。
仔细看,是存在的。csppsccsppsc。
第2,3,5,6,7,9字符连起来就是spsccp。
输出1。(输出布尔值真时,输出1,输出布尔值假时,输出0)

【答案】

  1. T
  2. F
  3. T
  4. D
  5. B
  6. D
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
2023 csp-j入门级第一轮是中国计算机科学会议(CSP)针对初学者设计的一道。根据目的具体要求,试内容可能涉及算法、编程语言、数据结构等方面的知识。 对于这样的试,学生们需要运用自己所学的知识和技能,通过编程实现目要求。例如,可能需要设计一个算法来解决一个具体的问,或者使用特定的数据结构来组织和处理数据。 为了完成这样的试,学生们首先需要理解目的要求和限制条件,确保对目中涉及的概念和术语有所了解。接下来,他们需要分析问,确定解决问的方法和步骤。在实际编程实现时,可以选择合适的编程语言和工具,并按照目要求进行编码。 在完成编码后,学生们需要进行测试和调试,确保程序能够正确运行并得到正确的结果。在测试过程中,可以使用一些已知的测试用例来验证程序的正确性,并对程序进行优化,以提高其性能。 最后,将代码提交,并等待评审结果。评审过程可能涉及代码质量、算法复杂度、正确性等方面的考量。根据评审结果,学生们可以了解自己的编程水平和不足之处,并进行相应的学习和提高。 总体来说,解答2023 csp-j入门级第一轮需要学生在编程基础上运用算法和数据结构的知识,进行问的分析和解决。通过这样的学习和实践,学生们可以提高自己的编程能力,并逐渐成长为优秀的程序员。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值