资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
考虑一种简单的正则表达式:
只由 x ( ) | 组成的正则表达式。
小明想求出这个正则表达式能接受的最长字符串的长度。例如 ((xx|xxx)x|(x|xx))xx 能接受的最长字符串是: xxxxxx,长度是6。
输入格式
一个由x()|组成的正则表达式。输入长度不超过100,保证合法。
输出格式
这个正则表达式能接受的最长字符串的长度。
样例输入
((xx|xxx)x|(x|xx))xx
样例输出
6
可以定性为一个字符串的表达式问题,拥有不同优先级多种运算。通常使用递归方法可以简明地写出。我们可以根据严谨的逻辑写出 dfs 函数,通过递归栈来帮助实现运算顺序。在本题当中,需要改变运算顺序的是括号出现的地方,其他地方可以直接顺序计算。
本题可以直接用一个 dfs 函数定义 算式的计算 ,在读到括号时嵌套调用 dfs 计算括号里的算式。
事实上,递归可以发生在多个函数之间,只需实现做好函数的签名即可。这是一种自顶向下的设计思路,我们可以把这个表达式的计算进一步细化为三个部分:表达式、因子、序列。
- 表达式 可以展开成
因子 | 因子 | ...这样用 或运算 连接的多个因子,值是其中因子的最大值。 - 因子 可以展开成
序列和(表达式)的任意排列,值是它们的和。 - 序列 就是一连串的 x,值是 x 的计数。
详见如下代码:
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
string s;
int i = 0; // s[i]
int n; // s.length()
int fact();
int seq();
// exp = fact | fact ...
int exp() {
int res = fact();
while (s[i] == '|') {
++i;
res = max(res, fact());
}
return res;
}
// fact = seq or (exp)seq ...
int fact() {
int res = 0;
while (i < n && (s[i] == '(' || s[i] == 'x')) {
if (s[i] == '(') {
++i;
res += exp();
++i; // ')'
} else if (s[i] == 'x') {
res += seq();
}
}
return res;
}
// xxx
int seq() {
int res = 0;
while (s[i] == 'x') {
++i;
++res;
}
return res;
}
int main() {
cin >> s;
n = s.size();
cout << exp() << endl;
return 0;
}
这样的思路有助于将复杂的问题拆解,每次只专心一个局部的实现,但是对于严谨性的要求也是一分不差的。尤其是对于更小规模问题的准确定义,不应当遗漏掉任何合法的情况。
本文探讨了一种正则表达式匹配问题,通过递归函数设计,解决只由'x()'|组成的表达式能接受的最长字符串长度。通过分解为因子、序列和表达式,展示了如何运用自顶向下策略求解并给出样例代码实现。
1269

被折叠的 条评论
为什么被折叠?



