题目描述
考虑一种简单的正则表达式:
只由 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);
}
}