小委出发vijos-1572 jdoj-1572

 

小委出发

    题目大意:一个长度为n的字符串,由()[]{}组成。求最长的和谐字符串:我们对最长和谐字符串的定义就是每一个括号有一个性质相同的括号与之匹配,这两个括号中间要么为空,要么也是和谐的。几个连续的和谐串连在一起也是和谐的。

    注释:k<=$5\cdot 10^6$

      想法:开始的想法是dp,怎么dp呢?我们设定dp[i]表示以第i个点为最后一个点的最长和谐子串。显然我们只需要记录一下每一个dp值的对应的位置即可,但是不好写,特判有些多,我们用一种很强的方式来解决这个问题(鸣谢Edward♂Frog)。我们用栈维护。如何用栈进行维护呢?如果当前元素是左边的括号,我就将其扔进栈里。如果当前元素是右括号,我就将它和栈顶元素进行比较,如果它和栈顶元素可以匹配,我就将它们双双弹出栈,将这两个元素的下标记为true,如果不是,我就清空栈。最后,从一到k每一个数对应true或false。我们只需要求最长的true的序列。这样为什么是对的?如果当前元素和栈顶元素相等,那么证明他们之间的元素是一定满足条件后被弹出的。所以,我们将这两个元素标记后,对于每一个和谐子串都一定有一串连续的1。我们只需要求最长的连续的1即可......

    最后,附上丑陋的代码......

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 int v[5000010];
 6 char s[5000010];
 7 int a[5000010];
 8 int x[5000010];
 9 int dp[5000010];
10 int main()
11 {
12     scanf("%s",s+1);
13     int k=strlen(s+1);
14     for(int i=1;i<=k;i++)
15     {
16         if(s[i]=='(') a[i]=1;
17         else if(s[i]=='[') a[i]=2;
18         else if(s[i]=='{') a[i]=3;
19         else if(s[i]=='}') a[i]=4;
20         else if(s[i]==']') a[i]=5;
21         else a[i]=6;
22     }
23     int top=0;
24     for(int i=1;i<=k;i++)
25     {
26         if(a[i]<=3)
27         {
28             x[++top]=i;
29         }
30         else
31         {
32             if(a[x[top]]+a[i]==7)
33             {
34                 v[x[top]]=1;
35                 v[i]=1;
36                 top--;
37             }
38             else top=0;
39         }
40     }
41     for(int i=1;i<=k;i++)
42     {
43         if(v[i])
44         {
45             dp[i]=max(dp[i],dp[i-1]+1);
46         }
47     }
48     int maxk=1;
49     int maxn=-1;
50     for(int i=1;i<=k;i++)
51     {
52         if(dp[i]>maxn) maxn=dp[i],maxk=i;
53     }
54     for(int i=maxk-maxn+1;i<=maxk;i++) printf("%c",s[i]);
55 }

 

    小结:错误,最后维护可以用并查集,虽然没必要

    未经博主允许,严禁转载

 

转载于:https://www.cnblogs.com/ShuraK/p/8003784.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值