历届试题 正则问题
问题描述
考虑一种简单的正则表达式:
只由x ( ) |
组成的正则表达式。
小明想求出这个正则表达式能接受的最长字符串的长度。
例如((xx|xxx)x|(x|xx))xx
能接受的最长字符串是:xxxxxx
,长度是 6。输入格式
一个由
x()|
组成的正则表达式。输入长度不超过 100,保证合法。输出格式
这个正则表达式能接受的最长字符串的长度。
样例输入
((xx|xxx)x|(x|xx))xx
样例输出
6
—— 柳暗花明——
对于题目给出的正则表达式,由于其存在着多重括号,那么对于某个式子而言其就必然需要用到回溯算法来对上一层括号中的内容进行反馈。换言之,本题用搜索算法来进行求解是相当合适的。
再看数据范围,输入字符串长度不超过100,这更一步确定了搜索算法的适用性。当然,是深度优先搜索。
接下来就以搜索算法的视角对本题进行分析。
首先要知道,当程序一遇到 (
时,我们就需要进入一层 dfs,这一层 dfs 的任务是确定在当前这对括号中其所能接受字符串的最大长度。尽管在当前的这对括号中,也许还有多重括号,但是请忽略掉这些,因为我们只需要关心当前 dfs 的当前搜索任务,更深一层的自然有其对应的 dfs 以完成。而当我们一遇到 )
(在当前 dfs 中),就说明已经将当前一对 ()
中的结果遍历完毕,接下来直接返回遍历的结果即可。
注意到在一对 ()
中是有可能遇到 |
运算的,这个的处理办法也很简单,我们事先定义两个变量
n
u
m
num
num 和
a
n
s
ans
ans 分别存放当前遍历某个连续 *
串的长度和当前遍历连续 *
串的最大长度,每当一遇到 |
时,我们就比较当前的
n
u
m
num
num 和
a
n
s
ans
ans,如果
n
u
m
num
num 更大就更新
a
n
s
ans
ans,否则
a
n
s
ans
ans 不变,最后令
n
u
m
=
0
num=0
num=0。
同样地,在某个 dfs 结束的时候(即遇到 )
的时候),我们也需要判断
a
n
s
ans
ans 是否需要更新,规则同上。而统计连续 *
串的长度的任务也就是通过
n
u
m
num
num 完成的了,即一遇到 *
就令
n
u
m
+
+
num++
num++。
细心的同学可能已经发现,上面的分析实际上就是一系列的 if 条件,而其后的行为描述正是 if 语句中所需要执行的代码。如果仍然对上面的描述不是很清晰的同学,建议直接看代码,如下:
—— 又一村 ——
#include<iostream>
#include<string>
using namespace std;
string str;
int pos,len;
int dfs()
{
int num=0,ans=0;
while(pos<len)
{
if(str[pos]=='('){
pos++;
num+=dfs();
}
else if(str[pos]==')'){
pos++;
break;
}
else if(str[pos]=='|'){
pos++;
ans=max(num,ans);
num=0;
}
else{
num++;
pos++;
}
}
ans=max(num,ans);
return ans;
}
int main()
{
cin>>str;
pos=0,len=str.length();
cout<<dfs()<<endl;
return 0;
}