【4002】括号序列

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;
}
原文地址:https://www.cnblogs.com/AWCXV/p/7632206.html