[蓝桥杯]正则问题(经典dfs)


题目链接

一、题目描述

考虑一种简单的正则表达式:
只由 x ( ) | 组成的正则表达式。
小明想求出这个正则表达式能接受的最长字符串的长度。

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

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

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

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

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

输出样例:
6

解题思路

题目很明显是dfs问题,不过比较有意思的是,该题和其他一般的深搜问题有点不一样,本题的树根节点有两种,我们都知道画出一个递归树对写dfs代码有很大帮助。对于样例来说,我们可以画出,这样一颗树
在这里插入图片描述
在本题根节点是遇到括号 和 | ,画出图来就很简单啦。 dfs写多了就知道深搜最重要处理的是返回值的位置,还有传参操作,至于其他的逻辑判断操作和我们正常代码无异。而搜索树中,通常再返回值就在树根处,这很容易理解吧,因为我们需要向下搜索,靠不断回溯来处理问题,那么放回值就应该是在搜索完后的节点处,就是我们的树根。新手最常犯的就是在写递归问题时用脑子一直去想递归,但是其实我们只需要处理几个关键点,剩下的再去debug一下就能解决

代码

针对本题我写了两种写法,第一种就是全局变量的方法来处理,好处是节省了一个数组空间标记,但可能有点难理解?

#include<bits/stdc++.h>
using namespace std;
string s;
int t = 0;
int dfs()
{
	int res = 0;
    while(t < s.size())
    {
    	if(s[t] == '(')
    	{
    		t ++;
    		res += dfs();
    // 		t ++;
		}
		else if(s[t] == '|')
		{
			t ++;
			res = max(res,dfs());
			return res;
		}
		else if(s[t] == ')')
		{
    		t ++;
			return res;
		}
		else
		{
			t ++ ;
			res ++ ;
		}
	}
	return res;
}
int main()
{
    cin >> s;
    cout<<dfs()<<endl;
    return 0;
}


下面这种就是常用的传参法了,需要加一个st数组来判断状态

#include<bits/stdc++.h>
using namespace std;
const int N = 110;
bool st[N];
string s;
int dfs(int t)
{
    int res = 0;
    for (int i = t; i < s.size(); i ++ )
    {
        if(!st[i])                                   //传参法深搜,需要进行标记,避免在循环中进行重复递归 
        {
            st[i] = 1;
            if(s[i] == '(')
            {
                res += dfs(i + 1);
            }
            else if(s[i] == '|')
            {
                res = max(dfs(i + 1),res);        
                return res;                           //此处返回很关键  这样才能避免res数据被覆盖 (返回值设在树的根节点,仔细观察树的结构) 
            }
            else if(s[i] == ')')
            {
                return res;
            }
            else{
                res ++ ;
            }
        }
    }
    return res;
} 
int main()
{
    cin >> s;
    cout<<dfs(0)<<endl;
    return 0;
}

总结

在这里插入图片描述
本题算是比较有代表性的搜索问题,再写dfs时,最好就是先画递归树,这样处理代码就能方便很多,也能解决掉返回值位置这个头大难的问题。

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

老帅比阿

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

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

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

打赏作者

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

抵扣说明:

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

余额充值