京東筆試:括號匹配 ---- 逆向思維題
阿新 • • 發佈:2019-02-15
題目:有一個合法的字串,合法是指左括號與右括號全部能配對,現在每次將這個序列第一個左括號刪去,在將任意一個右括號刪去,每次刪去後的序列必須合法,求有多少種方法,答案對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;
}