Codeforces - 990C

<Codeforces 990C>

题意:

给n个只由 '(' 和 ')' 组成的串,问从这些串中选出两个串,使他们括号匹配,能够成多少个匹配串,自身和自身组合匹配也算。以题中第二个样例说明:

输入:2 ( ) ( )

输出:4

解释:输入的两个串 a,b 分别是 a: ( ),b: ( ),所以共四种连接方式,即 a->a,a->b,b->a,b->b

思路:

说实话,这个思路,就是一种只可意会不可言传的感觉,我大概用我拙劣的语言,表述一下 T^T

我先对每个输入进来的串,进行如下操作:

int ln = s.length();
for(int j = 0; j < ln; j++) {
	if(s[j] == '(') l++;
	else {
		if(l) l--;
		else r++;
	}
}

这里的 l 代表,在输入进来的这个串中,不能与自身右括号形成匹配的左括号的个数;

r 则代表,在输入进来的这个串中,不能与自身左括号形成匹配的右括号的个数。

我已经进我最大努力表述了,自行脑补一下这里有一个笑哭的表情。。。注意听~

这样每个串无法在自身形成匹配的左右括号数就分别找出来了。

然后进行如下两步操作:

if(!l) R[r]++;
if(!r) L[l]++;

以上两步是核心代码,我尽我最大努力解释清楚,

首先明确两点,

(1)如果某个串里 l != 0 && r != 0,那这个串没法和任何一个串进行匹配

(2)有且仅有 x 个左括号不能在自身匹配的串, 它要想配对, 必须找有且仅有 x 个右括号不能在自身匹配的串

这也就是L[ ], R[ ]这两个数组的作用,如果 l == 0,那就意味着,这个串里有且仅有 r 个右括号匹配不到 ( r 可以取0),这样,它就必须找一个,有且仅有 r 个左括号匹配不到的的串,进行匹配。所以我在 l == 0 时,进行R[r]++,就是为了找到一个L[r]和当前的R[r]进行相乘再加入ans里,L[ ],R[ ]数组分别代表的值是仅有左括号不匹配,和仅有右括号不匹配的串的个数,而L[i], R[i]中的 i 值,则分别代表不匹配的左右括号各有几个。r == 0 同理。

本人AC代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <stack>
#include <ctime>
#include <cctype>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 3e5 + 7;
const int Inf = 1e9 + 7;
pair <int, int> a[maxn];
queue <int> qua;
set <int> sst;
vector <int> vect;
map <int, int> mp;
priority_queue < int, vector<int>, less<int> > qua1;
priority_queue < int, vector<int>, greater<int> > qua2;
int n;
string s;
ll L[maxn], R[maxn]; //有pos个左括号不能在自身匹配的串, 它要想配对, 必须找有pos个右括号不能在自身匹配的串
// 而L[pos]和R[pos]记录的就是左右括号与自身不匹配的串的个数, 即ans += L[pos] * R[pos]
ll ans;

int main() {
	cin >> n;
	int l, r; //记录每个串中左、右括号无法在该串自身内进行匹配的个数分别为多少
	for(int i = 1; i <= n; i++) {
		cin >> s;
		l = r = 0;
		int ln = s.length();
		for(int j = 0; j < ln; j++) {
			if(s[j] == '(') l++;
			else {
				if(l) l--;
				else r++;
			}
		}
		if(!l) R[r]++;
		if(!r) L[l]++;
	}
	for(int i = 1; i <= maxn; i++) ans += L[i] * R[i];
	ans += L[0] * R[0]; //自身就匹配的串的个数
	cout << ans << endl;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章