zoukankan      html  css  js  c++  java
  • 括号序列

    【题目描述】

    定义合法的括号序列如下:

    (1)空序列是一个合法的序列;

    (2)如果S是合法的序列,则(S)和[S]也是合法的序列;

    (3)如果A和B是合法的序列,则AB也是合法的序列;

    下面的都是合法的括号序列:

    ()、[]、(())、([])、()[]、()[()];

    下面的都是非法的括号序列:

    (、[、)、)(、([)]、([(];

    给定一个由(、)、[、]组成的序列,找出以该序列为子序列的最短合法序列。

    【输入描述】

    一行字符S(0 <= S <= 100)。

    【输出描述】

    一行字符,表示最短合法序列。

    【样例输入】

    ([)]

    【样例输出】

    ()[()]

    源代码:
    
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,f[101][101];
    char S[101];
    bool Match(char t1,char t2) //匹配判断。
    {
        return (t1=='('&&t2==')')||(t1=='['&&t2==']');
    }
    void DP() //动态规划。
    {
        for (int a=0;a<n;a++)
        {
            f[a+1][a]=0;
            f[a][a]=1;
        }
        for (int a=n-2;a>=0;a--) //从(n-2)才能将S分成两部分。
          for (int b=a+1;b<n;b++) //从当前节点到末尾。
          {
              f[a][b]=n; //符合实际的极大值。
              if (Match(S[a],S[b]))
                f[a][b]=min(f[a][b],f[a+1][b-1]); //Situation 1。
              for (int c=a;c<b;c++)
                f[a][b]=min(f[a][b],f[a][c]+f[c+1][b]); //Situation 2。
          }
    }
    void Print(int t1,int t2) //输出。
    {
        if (t1>t2) //数据不符合实际。
          return;
        if (t1==t2) //数据为单个字符。
        {
            if (S[t1]=='('||S[t1]==')')
              printf("()");
            else
              printf("[]");
            return;
        }
        int ans=f[t1][t2];
        if (Match(S[t1],S[t2])&&ans==f[t1+1][t2-1]) //Situation 1。
        {
            printf("%c",S[t1]);
            Print(t1+1,t2-1); //递归搜索。
            printf("%c",S[t2]);
            return;
        }
        for (int a=t1;a<t2;a++) //Situation 2。
          if (ans==f[t1][a]+f[a+1][t2])
          {
              Print(t1,a);
              Print(a+1,t2);
              return;
          }
    }
    int main()
    {
        gets(S); //可能含有空串,故scanf()不可行。
        n=strlen(S);
        DP();
        Print(0,n-1); //一步一步地穿越千山万水,回到起源的大地。
        printf("
    "); //我的
    不可能这么坑爹!
    }
    
    /*
        新奇的动归题目,输出也繁琐。
        设f[i][j]表示字符串S[i~j]至少需要添加的括号数,状态转移无非为以下两种情况:
            ①对应字符串S的f[]等于"[S]"或"(S)"对应的f[]。
            ②字符串S(S>=2)可划分为A、B两个子串,A、B所对应的f[]之和等于S对应的f[]。
        综上得状态转移方程:
            f[i][j]=min(f[i+1][j-1],f[i][k]+f[k+1][j](i<=k<j))。
        总结教训:
            看到一个题目最好先冷静分析一下,不必在意时间长短,脑子要灵活,不要觉得这道题好像用什么方法做就得用什么方法做。
    */
  • 相关阅读:
    transform 多值先后执行顺序
    css 清除浮动
    鼠标移动到图片,图片放大
    js 事件循环机制EventLoop
    web安全
    web前端踩坑记录
    滚动加载图片(懒加载)
    css 兼容问题
    模块化 AMD与CMD 规范
    css 盒子模型 ie盒子模型
  • 原文地址:https://www.cnblogs.com/Ackermann/p/5775716.html
Copyright © 2011-2022 走看看