题目大意:
给定“括号表达式“的归纳定义:
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, 索引,标记体