【第十题】括号匹配 | 字符串处理(北理工/北京理工大学/程序设计方法与实践/小学期)

目录

前言

程序

程序描述

个人心得




前言

这道题csdn上已经有现成的题解了,@贝贝今天AC了吗,这个博主写的挺好,贴一个网址

括号匹配 | 字符串处理_贝贝今天AC了吗的博客-CSDN博客

我当然是毫无疑问地参考了她的代码,之后自己画图敲了一遍,说一下自己的感受并且贴上代码吧。 

括号匹配的核心就在于,括号匹配本质上是一种消消乐,碰在一起的会消掉,而逐个放入,碰到就消的特征完美符合 “栈” 的特点,所以以后会遇到的括号匹配,()[]  {},其实原理都一模一样,就是栈。

栈的学习,emm,这个东西太简单了,不说c++已经封装好的栈,单是c语言,弄个数组,再配合一个指针就可以当栈用。

也就是说,其实我们早就在用各种数据结构了,只不过是我们不自知,从数组开始,到子序列自动机,都是数据结构,所谓数据结构,不过是人们在实践过程中,偶然想出来的数据组合方式,然后发现挺好用,诶,这就记录下来,一抽象,就成了某一种套路。


程序


程序描述

在乐学上出了一道给定括号序列,判断其合法性的问题。

括号序列是由左括号“(”和右括号“)”组成的非空序列。对于一个括号序列很容易判定其合法性。比如“()”、“(())()”、“(()())”、“(()(()))”、“()()()”都是合法的,而“)”、“(”、“(()”、“(()))(”都是非法的。

给定n个括号序列,两两配对,问最多能组成多少对合法括号序列。(每一个括号序列只能在一对中出现)

个人心得

因为后来是我自己敲得嘛,所以我把程序改了一下。

以前用函数,是因为对50-100行左右的整段代码把握能力不够,现在呢,经过10道程序设计和贪吃蛇的磨炼,我对50-100行整段代码已经习惯了,如果配合函数封装,努努力驾驭1000行模块化代码也不是没有问题,果然是,多敲促进具体的想法,重复思考会加深记忆组块的牢固程度,计算机学科,动手为纲。

这次我的改动主要是

  • 把模块化的东西做成整段,能整段我就懒得模块花了,打注释模块化即可。
  • 加了一大堆注释,非常容易理解。
  • 修改比较函数的结构,因为是短小函数,直接写在开头。
  • 修改了一下函数结构,就是按照自己的习惯改的,让结构更清晰,实际上我的反而看起来要更多一点。
  • 出现的问题是,不小心把大数组放main里了,人生第一次爆栈

上代码了

#include<stdio.h>
#include<string.h>
#include<stdbool.h>
#include<stdlib.h>
#define SIZE 100002
int match(char ch1, char ch2) 
{ return (ch1 == '(' && ch2 == ')') ? 1 : 0; };
//占内存的数组都放外面,不然分分钟把main栈撑爆,对我说的就是那个longlong
char str[SIZE];
char stack[SIZE];
long long left[SIZE] = { 0 }, right[SIZE] = { 0 };

int main(void)
{
	//left/right为记录化简后串的数组,
	//坐标:剩余的括号数 值:这类化简串的数量
	long long ct_empty = 0; //ct_empty记录化简为空的
	int n;
	int i, j;
	int len_str;
	int top;
	int ct_remain; //剩余括号数
	char ch_top;
	bool ispure;
	long long ans;
	scanf("%d\n", &n);//吸走字符,防止混淆

	//对每一串进行处理,统计各类别串数量
	for (i = 0; i < n; i++)
	{
		//化简
		memset(stack, 0, sizeof stack);//清空
		top = -1;
		ispure = true;
		scanf("%s", str);//读取,初始化,本来是想用gets_s来着,结果乐学识别不了
		len_str = strlen(str);
		for (j = 0; j < len_str; j++)//对str中字符逐个处理,化简str
		{
			if (top != -1 && match(stack[top], str[j]))//先判断是否为空,再进行匹配比较
				top--;//不仅不读入,还要弄出去一个
			else  //空的或者不匹配就把这个括号放进去
				stack[++top] = str[j]; //先加后赋值,top始终指向顶部元素
		}
		//对化简后串进行统计归类
		if (top == -1)//最后是空的了,就给空串计数
			ct_empty++;
		else //最后剩下了,再判断是都有,还是清一色
		{
			ch_top = stack[top];
			ct_remain = top + 1;
			while (top >= 0)//把栈内元素遍历
			{
				if (stack[top] != ch_top)//非清一色,换下一个
				{
					ispure = false;
					break;
				}
				top--;  //暂时清一色,继续遍历
			}
			if (ispure) //能走下来的,ispure是true
			{
				if (ch_top == '(')
					left[ct_remain]++;
				else
					right[ct_remain]++;
			}	
		}
	}
	//用统计归类后的数据计算结果
	ans = ct_empty / 2;
	for (i = 0; i < SIZE; i++)//没填充的默认是0,不会影响数据,放心遍历
		ans += left[i] > right[i] ? right[i] : left[i];

	printf("%lld\n", ans);
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

亦梦亦醒乐逍遥

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

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

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

打赏作者

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

抵扣说明:

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

余额充值