poj1068描述了这样一个问题:给出一种括号序列的表示形式名叫P序列,规则是统计出每个右括号之前的左括号个数作为序列每项的值。然后要求你根据这个求括号列的W序列值,W序列的规则是统计每一个右括号和与其匹配的左括号之间所有匹配后的括号个数。
刚看到这个题的时候,想法是十分简单的,就是模拟。我先用给的P序列推出括号序列,然后再去求W序列。后来我在discuss区发现一种十分不错的做法,贴在这里。
假定输入的P序列存在数组p中,则p[i]表示第i个P序列元素。
根据P序列的定义,每个数值表示的是当前这个右括号之前的左括号个数,而我们要求的是当前这个右括号之前的匹配的括号个数。
我们首先可以知道,所求与之后的括号情况无关,所以可以边读入边输出;
其次,由p[i]的定义可以知道p[i]-p[j]的意义:j第i个和第j个右括号中的左括号个数,而对于第i个括号而言(假定i > j ),这也是它可能的最大的W序列值(即第i个前
最多有p[i]-p[j]个匹配),对于 )( 这种而言,相邻两项间最多就能匹配一个。
所以我们可以写出关系:
int j = i - 1; while(p[i] - p[j] > i - j)j--;
当出现))时,while循环就会往前找知道找到匹配的左括号区域,然后在找的过程中累计。
完整代码如下:
#include <iostream> #include <stack> #include <cstring> using namespace std; int main(){ int N,a[30]; cin >> N; while(N--){ int n; cin >> n; a[0] = 0; for(int i = 1; i <= n; i++){ cin >> a[i]; int j = i - 1; while(a[i] - a[j] < i - j) j--; cout << (i-j) <<' '; } cout << endl; } return 0; }