您的位置:首页 > 其它

京东笔试:括号匹配 ---- 逆向思维题

2017-09-08 21:38 375 查看
一模一样的题 !!!

http://www.cnblogs.com/tbt123/p/6920729.html

题目:有一个合法的字符串,合法是指左括号与右括号全部能配对,现在每次将这个序列第一个左括号删去,在将任意一个右括号删去,每次删去后的序列必须合法,求有多少种方法,答案对10000000007。

输入:

一个合法括号序列。

输出:

方案数。


样例1:

Input:

()()()()

Output:

1


样例2:

Input

(((())))()()

Output:

24


首先我们很容易知道如果模拟的话很复杂,在进一步思考会发现从左到右走会有后效性,当前所选的右括号会决定序列是否合法且影响到下一次的选择,既然有后效性,那就倒过来,从右往左

可以证明到右边先选不会影响到左边。

附上简易的证明过程:首先明确左括号是能跟任意一个其右边的右括号匹配的,假设当前从右向左走到某一个左括号,右边的左括号已经全部满足了,左边的左括号也是能够满足,因为当前剩下的右括号全部在右边,也就是说现在任意选择一个右边的右括号与当前走到的左括号匹配都能保证剩余的右括号能与其左边的左括号匹配,即不会影响到整个序列的合法性。

定义一个ans记录方案数(这里有个坑,ans初始值为1!!!),再定义一个tot记录现在右边剩余的右括号,初始值为0,遇到右括号就加1,遇到左括号就减1。思路很清晰了,代码很容易写出。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cmath>
using namespace std;
const long long mod=10000000007ll;
char A[20000005];
long long ans=1;
int tot;
int main()
{

freopen("ka.in","r",stdin);
freopen("ka.out","w",stdout);
scanf("%s",A);
int len=strlen(A);
for(int i=len-1;i>=0;i--)
{
if(A[i]==')')tot++;
else if(A[i]=='('){
ans=(ans*tot)%mod;
tot--;
}
}
printf("%I64d",ans);
//printf("%lld",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: