匹配

实验任务

小光头解开了老鼠的难题,老鼠很高兴,告诉他们,他们需要打败控制这个森林的大魔王才能走出这片森林。如果小光头能再帮他解开一个难题,他就告诉小光头去哪里找这个大魔王。
问题是这样的,老鼠给了一串由由(,),[,],{,},<,>构成的一个括号字符串,找到它的一个最长子串,该子串有正确的括号配对。

数据输入

输入包括多组数据,每组数据只有一行括号字符串,其长度不大于 10000。

数据输出

对于每组数据,输出该括号字符串的最长配对子串。若答案不唯一,则输出最左边一个。
如果答案不存在,则输出“No Solution”。

输入示例

[()()]][]

输出示例

[()()]

解题思路

如果暴力扫描每个子序列,显然会超时。
我们不妨把序列中能匹配的括号标记为1。

[()()]][]
111111011

因此只要找到最长且连续的“1”序列,输出对应的括号即可。

参考代码

#include <iostream>   
#include <cstring>    
#include <map>    
#include <stack>  
const int maxn = 10010;    
using namespace std;    
map<char,char> m;  
struct P{  
    char c;  
    int id;  
}ss[maxn];  
char str[maxn]; //存 括号字符串 
int flag[maxn]; //存 每个括号能否被匹配 
int main()    
{  
    m[')'] = '(',m[']'] = '[';  //括号映射  
    m['}'] = '{',m['>'] = '<';  
    int i;  
    while(~scanf("%s",str)){  
        int len = strlen(str);  
        for (i = 0;i < len;i++){  
            ss[i].c = str[i];  
            ss[i].id = i;  
        } //把字符串复制到结构体中 
        memset(flag,0,sizeof(flag));  
        stack<P> s;  
        P temp = {'#',-1} ;  
        s.push(temp);    
        for (i = 0;i < len;i++){    
            if(m[ss[i].c] == s.top().c){  //如果括号能匹配
                flag[i] = 1;  
                flag [s.top().id] = 1;  //这两个位置的flag设为1(true)
                s.pop();    
            }    
            else    
                s.push(ss[i]);    
        }  
        int cnt=0,s1=0,s2=0,e1=0,e2=0; //cnt记录有多少个连续的1 ,s记录起点,e记录终点
        bool first = true;    
        for (i = 0;i < len;i++){  
            while (flag[i]){  
                if (first)  
                    s1 = i,first = false;  
                cnt++;  
                if (!flag[i+1])  
                    e1 = i,first = true;  
                i++;      
            }  
            if (e1 - s1 > e2 - s2)  //当前序列长度大于已存长度,则更新区间
                s2 = s1,e2 = e1;  
        }  
        if (!e2)  
            printf("No Solution");  
        else{  
            for (i = s2;i <= e2;i++)  
                printf("%c",ss[i].c);  
        }  
        printf("\n");  
    }    
    return 0;    
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值