括号匹配(二)
时间限制:
1000 ms | 内存限制:
65535 KB
难度:
6
-
描述
-
给你一个字符串,里面只包含"(",")","[","]"四种符号,请问你需要至少添加多少个括号才能使这些括号匹配起来。
如:
[]是匹配的
([])[]是匹配的
((]是不匹配的
([)]是不匹配的-
输入
-
第一行输入一个正整数N,表示测试数据组数(N<=10)
每组测试数据都只有一行,是一个字符串S,S中只包含以上所说的四种字符,S的长度不超过100
输出
- 对于每组测试数据都输出一个正整数,表示最少需要添加的括号的数量。每组测试输出占一行 样例输入
-
4 [] ([])[] ((] ([)]
样例输出
-
0 0 3 2
-
第一行输入一个正整数N,表示测试数据组数(N<=10)
分析: 设串S至少需要增加d(S)括号,转移如下:
1.如果s形如(S‘)或者[S'],转移到d(S')。
2.如果S至少有两个字符,则可分成AB,转移到d(A)+d(B).
边界是:S为空串是d(S) = 0, S为单字符串是d(S)=1。注意(S' , [S' , )S'之类全部属于第二种转移,不需要单独处理。
不管S是否满足第一条,都要尝试第二种转移,否则“[][]”会转移到"][",然后就只能加两个括号了。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int d[102][102], n;
char s[110];
int match(char a, char b) //括号匹配函数
{
return ((a == '(' && b == ')' )|| (a == '[' && b == ']'));
}
void dp()
{
int i, j, k;
for(i = 0; i < n; i++)
{
d[i][i] = 1;
d[i+1][i] = 0;
}
for(i = n-2; i >=0; i--)
{
for(j = i+1; j < n; j++)
{
d[i][j] = n;
if(match(s[i],s[j]))
d[i][j] = min(d[i][j], d[i+1][j-1]); //状态1转移
for(k = i; k < j; k++)
{
d[i][j] = min(d[i][j], d[i][k] + d[k+1][j]); //无论是否有状态1,全部转移状态2
}
}
}
}
int main()
{
//freopen("in.txt", "r", stdin);
int t;
scanf("%d", &t);
getchar();
while(t--)
{
memset(d, 0, sizeof(d));
gets(s);
n = strlen(s);
dp();
// for(int i = 0 ; i < n; i++)
// {
// for(int j = 0; j < n; j++)
// {
// printf("%d", d[i][j]);
// }
// printf("\n");
// }
// cout << endl;
printf("%d\n", d[0][n-1]);
}
return 0;
}