31. 括号序列

一个括号序列是指一个由'(', ')', '[', ']'四种字符组成的字符串。

一个只包含数字,加号'+',和上述四种括号的合法算数表达式,去掉数字和加号之后得到的括号序列成为合法的括号序列。我们定义空串也是合法的括号序列。

例如(1) + [2], ([3]), 4 + [5]相应的括号序列 "()[]", "([])", "[]"都是合法的括号序列。而(6 + 7], [8 + ((9对应的"(]", "[(("则是非法的。

字符串 s0s1s2s|s|1 的子串 s[l,r](0 lr<|s|) 是指 slsl+1sr

现在给定一个括号序列,请找出其中的一个子串,使得这个子串是合法的括号序列,且包含的'['数量最多。

输入

一个括号序列s。 1|s|5×105

输出

第一行,答案要求的子串中包含'['的数量。如果答案是0,输出到此为止,否则:第二行,两个整数l, r。表示子串第一个字符的位置和最后一个字符的位置。如果有多个满足条件的字符串,请输出使得子串长度最大的答案。如果长度最大的仍有多个,请输出r最大的。


测试输入关于“测试输入”的帮助期待的输出关于“期待的输出”的帮助时间限制关于“时间限制”的帮助内存限制关于“内存限制”的帮助额外进程关于“{$a} 个额外进程”的帮助
测试用例 1以文本方式显示
  1. ([])↵
以文本方式显示
  1. 1↵
  2. 0 3↵
1秒64M0


//处理出从字符串Str_S每一个位置i开始的最长的合法串,用Str_Node[i]记录
//其中Str_Node[i].Left== i,Str_Node[i].Right 为从i开始最长合法串的最右端
//Str_Node[i].Len = Right - Left + 1,这个数组的初始化可以在刚开始输入时进行
//用数组Str_Num[i]表示前i个元素中 ‘[’ 出现的次数,这个可以在字符串输入时进行
//则对于每个位置i,Str_Num[Str_Node[i].Right] - Str_Num[Str_Node[i].Left - 1]表示从i开始的最长合法串中的'['的个数
//关于Str_Node[]数组
//用数组Stack_Str模拟一个栈,用cur来表示栈尾指针
//栈中存储结构体StackStr,Stack_Str[cur].Ch表示栈尾的字符
//Stack_Str[cur].Loc表示栈尾字符是字符串Str_S中的第Loc个元素,如果栈尾是'('且栈头为')',那么弹出这栈尾元素(栈尾为'['时类似)
//第i次循环加入Str_S[i]之后,栈尾元素在Str_S中位置pp是Stack_Str[cur].Loc,
//那么如果i - pp大于0就把Str_Node[pp + 1].Right置为i,Str_Node[pp + 1].Len置为i - pp
//如此就可以O(n)维护Str_Node[]			
#include<stdio.h>//AC

char Str_S[600010] = { '\0' };
int Str_Num[600010] = { 0 };
typedef struct StrNode
{
	int Right;
	int Left;
	int Len;
}Strnode;
Strnode Str_Node[600010];
typedef struct StackStr
{
	char Ch;
	int Loc;
}StkStr;
StkStr Stack_Str[600010];
int main()
{
	int cch, StrLen = 0, cur = 0, ans = 0, ans_i;
	while (1)
	{
	aa:;
		cch=getchar();
		if (cch == 10)
			break;
		if (cch != '(' && cch != ')' && cch != '[' && cch != ']')
			goto aa;
		Str_S[StrLen+1] = cch;
		Str_Node[StrLen].Left = StrLen;
		Str_Node[StrLen].Len = 0;
		StrLen++;
		if (cch == '[')
			Str_Num[StrLen] = Str_Num[StrLen - 1] + 1;
		else
			Str_Num[StrLen] = Str_Num[StrLen - 1];
	}
	for (int i = 1; i <= StrLen; i++) 
	{
		StkStr Tvar = { Str_S[i] , i };
		if ((Stack_Str[cur].Ch == '(' &&Tvar.Ch == ')') || (Stack_Str[cur].Ch == '[' &&Tvar.Ch == ']')) 
			cur--;
		else 
			Stack_Str[++cur] = Tvar;
		int pp = Stack_Str[cur].Loc;
		if (Str_Node[pp + 1].Len < i - pp) 
		{
			Str_Node[pp + 1].Len = i - pp;
			Str_Node[pp + 1].Right = i;
		}
	}
	for (int i = StrLen; i >0 ; i--) //从小到大会WA,从大到小就不会
	{
		if (Str_Node[i].Len) 
		{
			int _ans = Str_Num[Str_Node[i].Right] - Str_Num[Str_Node[i].Left - 1];
			if (_ans > ans) 
			{
				ans = _ans;
				ans_i = i;
			}
			else if (_ans == ans) 
				if (Str_Node[i].Len >Str_Node[ans_i].Len) 
					ans_i = i;
		}
	}
	printf("%d\n", ans);
	if (ans) 
		printf("%d %d\n", Str_Node[ans_i].Left-1, Str_Node[ans_i].Right-1);

	return 0;
}





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值