POJ 2955 Brackets

题目大意:

        给定“括号表达式“的归纳定义:

        1. 空序列是一个括号表达式;

        2. 如果s是一个括号表达式则(s)和[s]也是括号表达式;

        3. 如果a、b都是括号表达式则ab也是括号表达式;

        4. 其余的都不是括号表达式;

        现有多个测例(以单词end表示结尾),每个测例中都给定一个只含括号(、)、[、]的序列,每个序列占一行,对于每个测例都求出序列中最长括号表达式的长度,即最大括号匹配数量,比如()的括号匹配数为2,而(]的匹配数为0,其中序列长度为[1, 100]。

题目链接

注释代码:

/*                                         
 * Problem ID : POJ 2955 Brackets
 * Author     : Lirx.t.Una                                         
 * Language   : C++                        
 * Run Time   : 47 ms                                         
 * Run Memory : 132 KB                                         
*/   

#include <string.h>
#include <stdio.h>

#define	TRUE			1
#define	FALSE			0

//maximum brackets length
//括号序列的最大长度
//最后一位留给'\0'
#define	MAXBRKTN		101

#define	MAX(x,y)		( (x) > (y) ? (x) : (y) )

typedef	int		BOOL;

char	brkt[MAXBRKTN];//bracket,括号序列
//dp[i][j]表示括号序列中下标为i到下标为j之间括号的
  //最大匹配数
char	dp[MAXBRKTN][MAXBRKTN];

BOOL
match( char a, char b ) {//检查两个括号是否匹配
    //第一个必为左括号,第二个必为右括号

	if ( '(' == a && ')' == b )
		return TRUE;
	
	if ( '[' == a && ']' == b )
		return TRUE;

	return FALSE;
}

int
main() {

	int		n;//括号个数
	int		i, j, k;//计数变量
	int		g;//gap,表示括号匹配的间隔

	while ( scanf("%s", brkt), *brkt != 'e' ) {

		n = strlen(brkt);

		for ( i = 0; i < n; i++ ) {//初始化

			dp[i][i] = 0;//自己到自己没有括号匹配

            //初始化所有间隔为1的括号匹配情况
			if ( match( brkt[i], brkt[i + 1] ) )
				dp[i][i + 1] = 2;
			else
				dp[i][i + 1] = 0;
		}

        //转移方程为:
        //dp[i][j] = MAX( dp[i + 1][j - 1] + 2(i、j必须匹配), MAX( dp[i][k] + dp[k + 1][j] )(1 ≤ k < j))
		for ( g = 2; g < n; g++ )//间隔从2开始递增到n - 1
			for ( i = 0, j = i + g; j < n; i++, j++ ) {
                //逐个扫描间隔为g的区间[i, j]的匹配情况
			
				dp[i][j] = 0;//先初始化为0

				if ( match( brkt[i], brkt[j] ) )//先检查特殊情况,即区间两个端点是否匹配
					dp[i][j] = dp[i + 1][j - 1] + 2;
				for ( k = i; k < j; k++ )//再在区间中[i, j - 1]上逐个设断点
                    //dp[i][j]必定是断点两边区间最大括号匹配数相加的值
                    //当然要从上述特殊情况以及所有断点分割情况中选出最大的最为dp[i][j]的最终值
					dp[i][j] = MAX( dp[i][j], dp[i][k] + dp[k + 1][j] );
			}

		printf("%d\n", dp[0][n - 1]);
	}
	
	return 0;
}

无注释代码:

#include <string.h>
#include <stdio.h>

#define	TRUE			1
#define	FALSE			0

#define	MAXBRKTN		101

#define	MAX(x,y)		( (x) > (y) ? (x) : (y) )

typedef	int		BOOL;

char	brkt[MAXBRKTN];
char	dp[MAXBRKTN][MAXBRKTN];

BOOL
match( char a, char b ) {

	if ( '(' == a && ')' == b )
		return TRUE;

	if ( '[' == a && ']' == b )
		return TRUE;

	return FALSE;
}

int
main() {

	int		n;
	int		i, j, k;
	int		g;

	while ( scanf("%s", brkt), *brkt != 'e' ) {

		n = strlen(brkt);

		for ( i = 0; i < n; i++ ) {

			dp[i][i] = 0;

			if ( match( brkt[i], brkt[i + 1] ) )
				dp[i][i + 1] = 2;
			else
				dp[i][i + 1] = 0;
		}

		for ( g = 2; g < n; g++ )
			for ( i = 0, j = i + g; j < n; i++, j++ ) {

				dp[i][j] = 0;

				if ( match( brkt[i], brkt[j] ) )
					dp[i][j] = dp[i + 1][j - 1] + 2;
				for ( k = i; k < j; k++ )
					dp[i][j] = MAX( dp[i][j], dp[i][k] + dp[k + 1][j] );
			}

		printf("%d\n", dp[0][n - 1]);
	}

	return 0;
}

单词解释:

regular:adj, 正规的,正则的,整齐的

inductive:adj, 归纳的

indice:n, 索引,标记体

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值