目录
前言
这道题csdn上已经有现成的题解了,@贝贝今天AC了吗,这个博主写的挺好,贴一个网址
我当然是毫无疑问地参考了她的代码,之后自己画图敲了一遍,说一下自己的感受并且贴上代码吧。
括号匹配的核心就在于,括号匹配本质上是一种消消乐,碰在一起的会消掉,而逐个放入,碰到就消的特征完美符合 “栈” 的特点,所以以后会遇到的括号匹配,()[] {},其实原理都一模一样,就是栈。
栈的学习,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;
}