一个括号序列是指一个由'(', ')', '[', ']'四种字符组成的字符串。
一个只包含数字,加号'+',和上述四种括号的合法算数表达式,去掉数字和加号之后得到的括号序列成为合法的括号序列。我们定义空串也是合法的括号序列。
例如(1) + [2], ([3]), 4 + [5]相应的括号序列 "()[]", "([])", "[]"都是合法的括号序列。而(6 + 7], [8 + ((9对应的"(]", "[(("则是非法的。
字符串 s0s1s2⋯s|s|−1 的子串 s[l,r](0≤ l≤r<|s|) 是指 slsl+1⋯sr 。
现在给定一个括号序列,请找出其中的一个子串,使得这个子串是合法的括号序列,且包含的'['数量最多。
输入
一个括号序列s。 1≤|s|≤5×105
输出
第一行,答案要求的子串中包含'['的数量。如果答案是0,输出到此为止,否则:第二行,两个整数l, r。表示子串第一个字符的位置和最后一个字符的位置。如果有多个满足条件的字符串,请输出使得子串长度最大的答案。如果长度最大的仍有多个,请输出r最大的。
//处理出从字符串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;
}