倪文迪陪你学蓝桥杯2021寒假每日一题:1.9日(2017省赛A第7题)

2021年寒假每日一题,2017~2019年的省赛真题。
本文内容由倪文迪(华东理工大学计算机系软件192班)和罗勇军老师提供。

后面的每日一题,每题发一个新博文,请大家看博客目录https://blog.csdn.net/weixin_43914593

题目链接:正则问题 http://oj.ecustacm.cn/problem.php?id=1321

1、题目描述


  一种简单的正则表达式:只由 x ( ) | 组成的正则表达式。
  小明想求出这个正则表达式能接受的最长字符串的长度。
  例如 ((xx|xxx)x|(x|xx))xx 能接受的最长字符串是: xxxxxx,长度是6


解释:
  正则表达式,又称规则表达式,通常被用来检索、替换符合某个模式(规则)的文本。
  比如题目中由 x ( ) | 组成的正则表达式,括号“()”的优先级最高,或操作“|”次之。括号里面是一个整体,或的两边保留最长的一个。
   ((xx|xxx)x|(x|xx))xx是怎么执行的,为什么是6呢?
  先执行括号,再执行或, 步骤是:
  (1)先看第一个括号,发现里面还有嵌套括号,找到最内部的括号,括号内是一个或操作。((xx|xxx)x|(x|xx))xx,得:(xxxx|(x|xx))xx
  (2)继续执行最内部括号。(xxxx|(x|xx))xx,得:(xxxx|xx)xx
  (3)继续执行最后括号。(xxxx|xx)xx,得:xxxxxx,结束,得长度为6的字符串。
  正则表达式教程:https://www.runoob.com/regexp/regexp-tutorial.html,它自带测试工具。

2、题解

  倪文迪的话:“这道题用递归的思路来做,代码还是相当简洁的。遇到左括号’(‘就去递归求解,遇到右括号’)‘则当前递归结束并返回结果;遇到’|‘则记录并重置当前的值,再向右计算更新;如果是x的话直接统计即可。”
  罗勇军老师的话:本题是练习DFS(递归)和栈的好题目
  题目的主体是括号匹配,这是经典的递归、栈的应用。
  (1)一个左括号必然有一个右括号匹配。读者可以尝试生成各种各样的嵌套括号,方法是:从第1对括号“()”开始;把第2对括号的左括号和右括号分别随机插入到第1对括号的任意位置,例如“(())”;把第3对括号随机插入,例如“(()())”,等等。只要括号是成对插入的,得到的括号串都是合法的。
  (2)用栈检查括号的合法性。每遇到一个左括号’(’,就进栈,每遇到一个右括号’)’,就完成了一次匹配,出栈。读者可以用一个嵌套括号来练习练习。
  (3)编码。可以直接用栈编码,也可以用DFS(递归)编码,更简单一点。(参考这篇博文,它介绍了栈、队列、堆等,并给出了各种代码实现:简单数据结构
  本题的字符串除了括号,还有’|‘和’x’。’|'和’x’的处理和括号的递归处理有关,这使得代码的逻辑有点复杂。请尝试自己编码,然后对照下面的代码。
  下面给出了C++、Java、Python代码。Python确实很慢。

3、C++代码

  交到OJ,运行时间0s

#include<bits/stdc++.h>
using namespace std;

string s;
int pos = 0;       //当前的位置

int dfs(){
	int tmp = 0, ans = 0;
	int len = s.size();
	while(pos < len){
		if(s[pos] == '('){   //左括号,继续递归。相当于进栈
			pos++;
			tmp += dfs();
		}else if(s[pos] == ')'){   //右括号,递归返回。相等于出栈
			pos++;
			break;
		}else if(s[pos] == '|'){   //检查或
			pos++;
			ans = max(ans, tmp);
			tmp = 0;
		}else{                     //检查X,并统计X的个数
			pos++;
			tmp++;
		}
	}
	ans = max(ans, tmp);
	return ans;
}

int main(){
	cin >> s;
	cout << dfs() << endl;
	return 0;
}

4、Java代码

  OJ上运行时间1.3s

//User: 1240276522

import java.util.Scanner;
 
public class Main {
    static String s;
    static int pos;
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        s = sc.nextLine();   
        System.out.println(dfs());
    }
    public static int dfs() {
        int ans = 0;
        int temp = 0;
        int len = s.length();
        while (pos < len) {
            if(s.charAt(pos) == '(') {
                pos++;
                temp += dfs();
            } else if(s.charAt(pos) == 'x') {
                temp++;
                pos++;
            }else if(s.charAt(pos) == '|') {
                ans = Math.max(ans,temp);
                temp = 0;
                pos++;
            } else if(s.charAt(pos) == ')') {
                pos++;
                return Math.max(temp,ans);
            }
        }
        return Math.max(ans,temp);
    }
}

5、Python代码

  OJ运行时间超过3s。Python果然慢。

s = input()
count, pos, length = 0, 0, len(s)

def dfs():
    global length, pos
    temp, ans = 0, 0
    while pos < length:
        if s[pos] == '(':
            pos += 1
            temp += dfs()
        elif s[pos] == 'x':
            pos += 1
            temp += 1
        elif s[pos] == '|':
            pos += 1
            ans = max(ans, temp)
            temp = 0
        elif s[pos] == ')':
            pos += 1
            ans = max(ans, temp)
            return ans
    ans = max(ans, temp)
    return ans 
 
ans = dfs()
print(ans)
  • 14
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罗勇军

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值