(2017)第八届蓝桥杯大赛个人赛省赛(软件类) C/C++ 大学A组 题解(第七题)

前言

回老家ing,火车的信号一点儿也不好,能充电的地方桌子又小小的= =||

祝大家新年快乐=w=


程序设计题目区

程序设计题目:要求选手设计的程序对于给定的输入能给出正确的输出结果。考生的程序只有能运行出正确结果才有机会得分

注意:在评卷时使用的输入数据与试卷中给出的示例数据可能是不同的。选手的程序必须是通用的,不能只对试卷中给定的数据有效。

对于编程题目,要求选手给出的解答完全符合ANSI C++标准,不能使用诸如绘图、Win32API、中断调用、硬件操作或与操作系统相关的API。

代码中允许使用STL类库。

注意: main函数结束必须返回0

注意: 所有依赖的函数必须明确地在源文件中 #include , 不能通过工程设置而省略常用头文件。

所有源码必须在同一文件中。调试通过后,拷贝提交。

提交时,注意选择所期望的编译器类型。

程序设计的题分值往往都很高,当然想完全正确是很难的。这些题目的给分方法是根据若干评测数据来给分,也就是说,你的程序过了一个数据,你就可以拿到一点分。那么,我们在无法保证完全正确的情况下,优先选择部分正确的方法即可。

如果你完成了部分正确的程序代码,你应该先自己构造数据,检验你的程序的正确性,然后再接着往下做。

这里有一个常用的技巧,你可以去写一个实现简单,正确率高,但不满足时间空间限制的程序,用这个程序和你的题目答案跑相同的数据,对比它们是否有不同。甚至你可以去写一个程序去完成这项工作(称之为对拍,有机会我会讲讲)。

遇到一点儿也不会的题,你可以直接跳过,回头再做。

还有一个很重要的点:你应该严格遵守题目的输出要求。一些提示性的“ans=”或者打印一些其它的数据都是不行的。

一些常用知识:

(1)1s时限一般可以满足10^8次的运算。

(2)1个int要占用4B,1个char要占用1B,1个long long 或 double 要占用8B


第七题

题目

描述:正则问题
考虑一种简单的正则表达式:
只由 x ( ) | 组成的正则表达式。
小明想求出这个正则表达式能接受的最长字符串的长度。  
例如 ((xx|xxx)x|(x|xx))xx 能接受的最长字符串是: xxxxxx,长度是6。
输入
----
一个由x()|组成的正则表达式。输入长度不超过100,保证合法。  
输出
----
这个正则表达式能接受的最长字符串的长度。  
例如,
输入:
((xx|xxx)x|(x|xx))xx  
程序应该输出:
6  
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗  < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
注意:
main函数需要返回0;
只使用ANSI C/ANSI C++ 标准;
不要调用依赖于编译环境或操作系统的特殊函数。
所有依赖的函数必须明确地在源文件中 #include
不能通过工程设置而省略常用头文件。

提交程序时,注意选择所期望的语言类型和编译器类型。

第一个程序

分析

首先要理解题意。如果你不了解正则表达式的话,你应该想办法猜出这个式子的含义。

很明显,题目要求的意思是求最多能放多少个x。

那么()我们很容易猜出来,是用来决定运算先后顺序的,这个“|”是个什么呢?

应该是一种运算,而且是一种跟字符串相关的运算。

那么我们就设想各种各样的运算,将其带入式子中,看看样例符不符合:

拼接:11 取长:6 取短:3

那么“|”应该就是取长的意思了。

实际上,“|”在正则表达式里的意思是逻辑或运算,也就是两者取其一。

由于我们求最大的,所以每次都选择长的哪个。

现在我们来完成这道题目吧。

首先,在不考虑“|”的情况下,我们发现这道题就是一个数有多少个“x”的问题。

如果你觉得考虑“|”会非常难,你应该先实现这个简单的版本(给多少分我就不清楚了= =)

代码及运行结果

#include 
#include 
using namespace std;
int main() {
    string str;
    cin >> str;
    int len = str.length(), ans = 0;
    for (int i = 0; i < len; i++) {
        if (str[i] == 'x') {
            // 如果你不清楚字母具体是什么,就把题目里的字母拷贝过来,保证正确性
            ans++;
        }
    }
    cout << ans << endl;
    return 0;
}

运行结果:

(2017)第八届蓝桥杯大赛个人赛省赛(软件类) C/C++ 大学A组 题解(第七题)_第1张图片

第二个程序

分析

我们来考虑包含“|”的情况。假设没有括号,那么你就会发现你要求的只是在若干个x字符串里找一个最长的。

那么我们就按照上面的写法稍加改进。

代码及运行结果

#include 
#include 
using namespace std;
int main() {
    string str;
    cin >> str;
    int len = str.length(), ans = 0, num = 0;
    for (int i = 0; i < len; i++) {
        if (str[i] == 'x') {
            // 如果你不清楚字母具体是什么,就把题目里的字母拷贝过来,保证正确性
            num++;
        }
        else if (str[i] == '|') {
            ans = max(num, ans);
            num = 0;
        }
    }
    ans = max(num, ans);
    cout << ans << endl;
    return 0;
}

一般情况下,你都可以在写新的程序时沿用旧内容的部分程序,节省思考和编写的时间。

运行结果:

(2017)第八届蓝桥杯大赛个人赛省赛(软件类) C/C++ 大学A组 题解(第七题)_第2张图片

第三个程序

分析

当我们需要同时考虑“()”和“|”时,我们发现“()”括号的作用就是讲上面的代码限定了一个范围,所以我们只需要让这段代码从一个“(”开始运行到一个“)”为止。

那么怎么才能做到这种控制呢?

我们可以分析一下样例的计算过程。

(2017)第八届蓝桥杯大赛个人赛省赛(软件类) C/C++ 大学A组 题解(第七题)_第3张图片

在遇到一个括号时,我们会先终止当前的计算,进入到括号里进行计算,当这一次计算结束后,我们返回这个结果继续计算。

这是一个和深搜回溯很相似的过程(还记得第四题吗)。

所以我们用深搜的方式来完成计算。在遇到一对“()”时,我们就进入一个新的函数,然后用这个函数的返回值继续计算。

代码及运行结果

#include 
#include 
using namespace std;
string str;
int pos, len;
int dfs() {
    int num = 0, res = 0;
    while (pos < len) {
        if (str[pos] == '(') {
            pos++;
            num += dfs();
        }
        else if (str[pos] == ')') {
            pos++;
            break;
        }
        else if (str[pos] == '|') {
            pos++;
            res = max(num, res);
            num = 0;
        }
        else {
            pos++;
            num++;
        }
    }
    res = max(num, res);
    return res;
}
int main() {
    cin >> str;
    int ans = 0;
    len = str.length(), pos = 0;
    ans = dfs();
    cout << ans << endl;
    return 0;
}

运行结果

(2017)第八届蓝桥杯大赛个人赛省赛(软件类) C/C++ 大学A组 题解(第七题)_第4张图片

你可能感兴趣的:(蓝桥杯,蓝桥杯,算法,题解)