zoukankan      html  css  js  c++  java
  • NYOJ15括号匹配

    NYOJ15括号匹配

    括号匹配(二)

    时间限制:1000 ms  |  内存限制:65535 KB
    难度:6
     
    描述
    给你一个字符串,里面只包含"(",")","[","]"四种符号,请问你需要至少添加多少个括号才能使这些括号匹配起来。
    如:
    []是匹配的
    ([])[]是匹配的
    ((]是不匹配的
    ([)]是不匹配的
     
    输入
    第一行输入一个正整数N,表示测试数据组数(N<=10)
    每组测试数据都只有一行,是一个字符串S,S中只包含以上所说的四种字符,S的长度不超过100
    输出
    对于每组测试数据都输出一个正整数,表示最少需要添加的括号的数量。每组测试输出占一行
    样例输入
    4
    []
    ([])[]
    ((]
    ([)]
    样例输出
    0
    0
    3
    2
    来源
    《算法艺术与信息学竞赛》

    分析

    二维数组dp[i][j] 表示字符串s的第i..j字符需要最少括号数,下面是具体的表示:

    当i= j的时候,只有一个字符,那么,只要匹配一个字符就行了,所以,dp[i][i] = 1

    如果,当i < j的时候,s[i] = s[j]  那么,dp[i][j] = min(dp[i][j],dp[i+1][j+1]),其中,假设i <= k < j 状态转移方程为 dp[i][j] = min(dp[i][j],d[i][k] + dp[k+1][j])

    换个角度,换个方向

    分析:我们求出这个串的最大匹配,然后串的总长度-最大匹配就是答案。

    方法1:首先能想到的是转化成LCS(最长公共子序列),枚举中间点,求所有的LCS中的最大值 * 2就是最大匹配。但是复杂度较高,光LCS一次就O(n^2)的复杂度。

    方法2:

    首先考虑怎么样定义dp让它满足具有通过子结构来求解、

    定义dp [ i ] [ j ] 为串中第 i 个到第 j 个括号的最大匹配数目

    那么我们假如知道了 i 到 j 区间的最大匹配,那么i+1到 j+1区间的是不是就可以很简单的得到。

    那么 假如第 i 个和第 j 个是一对匹配的括号那么dp [ i ] [ j ] = dp [ i+1 ] [ j-1 ] + 2 ;

    那么我们只需要从小到大枚举所有 i 和 j 中间的括号数目,然后满足匹配就用上面式子dp,然后每次更新dp [ i ] [ j ]为最大值即可。

    更新最大值的方法是枚举 i 和 j 的中间值,然后让 dp[ i ] [ j ] = max ( dp [ i ] [ j ] , dp [ i ] [ f ] + dp [ f+1 ] [ j ] ) ;

     1 #include <stdio.h>
     2 #include <string.h>
     3 
     4 #define min(x,y) (x < y ? x : y)
     5 #define MAX 101
     6 
     7 int dp[MAX][MAX];
     8 
     9 bool cmp(int n,int m)
    10 {
    11     if((n == '('&&m == ')')||(n == '['&&m == ']'))
    12     return 1;
    13     else
    14     return 0;
    15 }
    16 
    17 int main(void)
    18 {
    19     int n,m,i,j,k;
    20     char str[101];
    21     scanf("%d",&n);
    22     while(n--)
    23     {
    24         scanf("%s",str);
    25         int length = strlen(str);
    26         memset(dp,0,sizeof(dp));
    27         for(i = 0; i < length; i++)
    28         {
    29             dp[i][i] = 1;
    30         }
    31         //区间dp常用dp套路 
    32         for(m = 1; m < length; m++)//枚举的串长度 
    33         {
    34             for(i = 0; i < length - m; i++)//起点 
    35             {
    36                 j = i + m;//终点 
    37                 dp[i][j] = MAX; //初始值 
    38                 if(cmp(str[i],str[j]))  
    39                 dp[i][j] = min(dp[i][j],dp[i+1][j-1]);//消去匹配的括号
    40                 //枚举中间点 
    41                 for(k = i; k < j; k++)
    42                 {
    43                    dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]);
    44                 }
    45             }
    46         }
    47         printf("%d
    ",dp[0][length-1]);
    48     }
    49     return 0;
    50 }
  • 相关阅读:
    docker 上的第一个网址
    redis 和mongodb的区别
    在docker 里 搭建redis 主从节点
    .Net AOP 的简单入门 (静态代理 适配器模式完成aop)
    CocoaPods pod install下载慢问题
    [OC]OC基础概念
    [Swift]swift之随机数
    [Swift]iOS开发之气泡对话框的实现
    [Swift]CoreData防止数据冲突
    [Swift]iOS开发之初识CoreData
  • 原文地址:https://www.cnblogs.com/Renyi-Fan/p/7421122.html
Copyright © 2011-2022 走看看