Time Limit: 3 second
Memory Limit: 2 MB
【问题描述】
定义如下规则序列(字符串):
1.空序列是规则序列;
2.如果S是规则序列,那么(S)和[S]也是规则序列;
3.如果A和B都是规则序列,那么AB也是规则序列;
例如,下面的字符串都是规则序列:
(),[],([]),([]),()[],()[()]
而以下几个则不是:
(,[,],)(,()),([()
如([])、[()]、[[]]、(())称为嵌套一层的规则序列;如[[[]]]、[[()]]、[([])]、[[()]]、(([]))称为嵌套二层的规则序列。
现在,给你一些由“(”,“)”,“[”,“]”构成的序列,你要做的,是找出一个规则序列,使得给你的那个序列是你给出的规则序列的子列(对于序列a1,a2,…,an和序列b1,b2,…,bm,如果存在一组下标1≤i1<i2<…<in≤m,使得ak=bij,对于1<=k<=n成立,那么a1,a2,…,an就叫做b1,b2,…,bm的子列),你所给出的序列不能破坏原有序列中的规则部分,并且你所给出的序列应是嵌套层数最少的最短序列。
【输入】
输入文件仅一行,全部由“(”,“)”,“[”,“]”组成,没有其他字符,长度不超过100。
【输出】
输出文件也仅有一行,全部由“(”,“)”,“[”,“]”组成,没有其他字符,把你找到的规则序列输出即可。
【输入样例】
([()
【输出样例】
()
【题解】
感觉不是很好的题。
如果是左括号(不论是什么类型都入栈),然后如果是右括号就和栈顶的尝试匹配。如果不匹配。就强行在这个位置匹配一个()或[]并标记这里已经强行匹配了、栈保持原状不动。若是匹配。则栈顶指针递减。最后把栈内剩余的元素所在的也强行匹配成()或[];
最后扫描一遍,如果是强行匹配的就输出那个匹配。否则就输出它原本是啥。
不知道出题人怎么想的。
【代码】
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
const int MAX_LONG = 100000;
string s,temp;
int a[MAX_LONG],c[MAX_LONG],b[MAX_LONG];
int main()
{
//freopen("F:\\rush.txt", "r", stdin);
cin >> s;
int len = s.size();
for (int i =0;i <= len-1;i++)
switch (s[i])
{
case '(':a[i + 1] = c[i+1] = -1; break;
case '[':a[i + 1] = c[i+1] = -2; break;
case ')':a[i + 1] = c[i+1] = 1; break;
case ']':a[i + 1] = c[i+1] = 2; break;
}
int k = 0;
for (int i = 1; i <= len; i++)
if (a[i] < 0)
{
k++;
b[k] = i;
}
else
if ((a[b[k]] + a[i]) != 0)//强行匹配
c[i] = 0;
else
k--;
for (int i = 1; i <= k; i++)
c[b[i]] = 0;
for (int i = 1; i <= len; i++)
if (c[i] == 0)//如果要强行匹配
{
switch (abs(a[i]))
{
case 1:printf("()"); break;
case 2:printf("[]"); break;
}
}
else
putchar(s[i-1]);
return 0;
}