蓝桥杯正则问题

题目描述

考虑一种简单的正则表达式:

只由 x ( ) | 组成的正则表达式。

小明想求出这个正则表达式能接受的最长字符串的长度。

例如 ((xx|xxx)x|(x|xx))xx 能接受的最长字符串是: xxxxxx,长度是6。

输入格式
一个由x()|组成的正则表达式。

输出格式
输出所给正则表达式能接受的最长字符串的长度。

数据范围
输入长度不超过100,保证合法。

输入样例
((xx|xxx)x|(x|xx))xx

输出样例
6

java代码

想起来之前处理过一个用栈实现的加减乘除简答运算。
大体思路是将遇到的操作符和运算数分别用两个栈表示,扫描字符串,遇到不同的字符做出相应的处理。
在蓝桥杯练习系统中只能拿到62分。
该代码在处理到xx(xx|xxx)时会有问题,此处不展开解释,跟着代码走一遍就明白了。

import java.util.*;

public class Main {
	static String str = new String();
	static Stack<Integer> ans = new Stack<Integer>();
	static Stack<Character> op = new Stack<Character>();

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		str = sc.next();
		ans.push(Integer.valueOf(0));

		for (int i = 0; i < str.length(); i++) {
			char ch = str.charAt(i);
			switch (ch) {
			case '(':
				op.push(Character.valueOf(ch));
				break;
			case ')':
				while (true) {
					char tmp = op.pop();
					if (tmp == '(') {
						break;
					}
					if (tmp == '|') {
						Integer i1 = ans.pop();
						Integer i2 = ans.pop();
						ans.push(Math.max(i1, i2));
					}
				}
				break;
			case '|':
				op.push(Character.valueOf(ch));
				ans.push(Integer.valueOf(0));
				break;
			case 'x':
				Integer tmp = ans.pop();
				tmp += 1;
				ans.push(tmp);
				break;
			}
		}
		
		while (true) {
			Integer i1 = ans.pop();
			if (ans.size()==0) {
				System.out.println(i1);
				break;
			} else {
				Integer i2 = ans.pop();
				ans.push(Math.max(i1, i2));
			}
		}
		
	}
}

java代码2

此处的思路是用一个pos记录到当前处理的位置,循环直到pos>=str的长度。
扫描到不同的符号做相应的处理。
不同之处在于此处没有用栈结构,而是用循环和递归结合,很好地解决了xx(xxx|xxxx)的问题。
该代码处理了所有的情况,可以拿到满分。

import java.util.*;

public class Main {
	static String str = new String();
	static int len = 0; // 存储字符串的长度
	static int pos = 0; // 记录当前处理的字符下标

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		str = sc.next();
		len = str.length();

		System.out.println(f());
		sc.close();

	}

	private static int f() {
		int preMax = 0; // 暂存之前的最大长度
		int tmp = 0; // 当前处理的最大长度
		// 用全局变量pos扫描,使得进入递归后仍然可以处理
		while (pos < len) {
			switch (str.charAt(pos)) {
			case '(':
				pos++;
				tmp += f(); // 去处理当前遇到左括号直到一个右括号的字符串
							// 很好地处理了xx(xxx)的情况
				break;
			case 'x': // 匹配到x,没什么好说的
				pos++;
				tmp++;
				break;
			case '|': // 这里用max赋值给preMax,是为了解决xx|xxx|xxxx的情况
				pos++;
				preMax = Math.max(preMax, tmp);
				// preMax = tmp; 如果用这样的语句,不能处理xx|xxx|xxxx的情况
				tmp = 0;
				break;
			case ')': // 扫描到),说明当前括号处理结束,返回preMax和tmp中的最大值
						// 解决了(xx|xxx)的情况
				pos++;
				return Math.max(preMax, tmp);
			}
		}
		// 解决xx|xxx|xxxx的情况
		return Math.max(preMax, tmp);
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值