題意
- 給定一個非空的字串,其由(,),?三個字元構成,其中?可以被(或者)給替換掉,求替換後的字串是符合括號匹配的情況下的方案數。最後答案對mod=998244353取模
思路
- 應該算是一個板題,一開始的想法是往卡特蘭數的方向思考,但是可能是我太水了沒想出來,然後一想到卡特蘭數的dp求法,就順理成章的想到了dp。
- 我們將(替換成1,)替換成-1,對於一個合法的括號匹配來說,對於任何一項i,我們都有字首和為正數,否則就不合法了。我們定義dp[i][j]為到達字串的第i位,字首和為j的情況下的方案數,那麼我們就可以很容易得出狀態轉移方程:
- dp[i][j]=dp[i-1][j-1],(a[i]==1)
- dp[i][j]=dp[i-1][j+1]+dp[i-1][j-1],(a[i]==0)
- dp[i][j]=dp[i-1][j+1],(a[i]==-1)
- 注意一下字串的開頭,當j==0時,防止陣列越界,我們單獨處理一下。當然注意取模,先取模後相加。
程式碼
string s;
cin>>s;
int n=s.length();
dp[0][0]=1;
for(int i=1;i<=n;i++)
{
if(s[i-1]=='(') a[i]=1;
else if(s[i-1]==')') a[i]=-1;
else a[i]=0;
}
for(int i=1;i<=n;i++)
{
for(int j=0;j<=i;j++)
{
if(a[i]==1) dp[i][j]=dp[i-1][j-1]%mod;
else if(a[i]==0)
{
if(i==1&&j==0) dp[i][j]=0;
else dp[i][j]=(dp[i-1][j+1]%mod+dp[i-1][j-1]%mod)%mod;
}
else dp[i][j]=dp[i-1][j+1]%mod;
}
}
cout<<dp[n][0]%mod<<endl;
return 0;
}