題目描述:spa
咱們給出 S,一個源於 {'D', 'I'} 的長度爲 n 的字符串 。(這些字母表明 「減小」 和 「增長」。)
有效排列 是對整數 {0, 1, ..., n} 的一個排列 P[0], P[1], ..., P[n],使得對全部的 i:code
若是 S[i] == 'D',那麼 P[i] > P[i+1],以及;
若是 S[i] == 'I',那麼 P[i] < P[i+1]。
有多少個有效排列?由於答案可能很大,因此請返回你的答案模 10^9 + 7.blog
示例:字符串
輸入:"DID"
輸出:5
解釋:
(0, 1, 2, 3) 的五個有效排列是:
(1, 0, 3, 2)
(2, 0, 3, 1)
(2, 1, 3, 0)
(3, 0, 2, 1)
(3, 1, 2, 0)string
提示:io
1 <= S.length <= 200
S
僅由集合 {'D', 'I'}
中的字符組成。
思路分析:class
咱們用 dp(i, j) 表示肯定了排列中到 P[i] 爲止的前 i + 1 個元素,而且 P[i] 和未選擇元素的相對大小爲 j 的方案數(即未選擇的元素中,有 j 個元素比 P[i] 小)。在狀態轉移時,dp(i, j) 會從 dp(i - 1, k) 轉移而來,其中 k 表明了 P[i - 1] 的相對大小。若是 S[i - 1] 爲 D,那麼 k 不比 j 小;若是 S[i - 1] 爲 I,那麼 k 必須比 j 小。集合
代碼:di
1 class Solution { 2 public: 3 int mod = 1e9+7; 4 int numPermsDISequence(string S) { 5 int n = S.size(); 6 if(n==0) 7 return 0; 8 vector<vector<int>> dp(n+1, vector<int>(n+1, 0)); 9 for(int i=0; i<n+1; i++) 10 dp[0][i]=1; 11 for(int i=1; i<=n; i++) 12 { 13 for(int j=0; j<=i; j++) 14 { 15 if(S[i-1]=='D') 16 { 17 for(int k=j; k<i; k++) 18 { 19 dp[i][j] += dp[i-1][k]; 20 dp[i][j] %= mod; 21 } 22 } 23 else 24 { 25 for(int k=0; k<j; k++) 26 { 27 dp[i][j] += dp[i-1][k]; 28 dp[i][j] %= mod; 29 } 30 } 31 } 32 } 33 int ans = 0; 34 for(int i=0; i<=n; i++) 35 { 36 ans += dp[n][i]; 37 ans %= mod; 38 } 39 return ans; 40 } 41 };