Giả sử chúng ta có một chuỗi S. Đây là một chuỗi các ký tự từ tập {'D', 'I'}. (D có nghĩa là "giảm" và I có nghĩa là "tăng")
Bây giờ hãy coi một hoán vị hợp lệ là một hoán vị P [0], P [1], ..., P [n] của các số nguyên {0 đến n}, sao cho với mọi i, nó đáp ứng các quy tắc sau:
-
Nếu S [i] =='D' thì P [i]> P [i + 1];
-
Ngược lại khi S [i] =='I' thì P [i]
Ta phải tìm xem có bao nhiêu hoán vị hợp lệ? Câu trả lời có thể rất lớn, vì vậy chúng tôi sẽ quay lại bằng cách sử dụng mod 10 ^ 9 + 7.
Vì vậy, nếu đầu vào giống như "IDD", thì đầu ra sẽ là 3, Vì vậy, sẽ có ba hoán vị khác nhau, chúng giống như (0,3,2,1), (1,3,2,0), ( 2,3,1,0).
Để giải quyết vấn đề này, chúng tôi sẽ làm theo các bước sau -
-
n:=kích thước của S
-
Xác định một dp mảng 2D có kích thước (n + 1) x (n + 1)
-
để khởi tạo j:=0, khi j <=n, cập nhật (tăng j lên 1), thực hiện -
-
dp [0, j]:=1
-
-
để khởi tạo i:=0, khi i
-
nếu S [i] giống với 'I', thì -
-
để khởi tạo j:=0, curr:=0, khi j
-
curr:=(dp [i, j] + curr) mod m
-
dp [i + 1, j] =(dp [i + 1, j] + curr)
-
-
-
nếu không thì
-
để khởi tạo j:=n - i - 1, curr:=0, khi j> =0, cập nhật (giảm j đi 1), làm -
-
curr:=(dp [i, j + 1] + curr) mod m
-
dp [i + 1, j] =(dp [i + 1, j] + curr)
-
-
-
-
trả về dp [n, 0]
Hãy cùng chúng tôi xem cách triển khai sau để hiểu rõ hơn -
Ví dụ
#include <bits/stdc++.h> using namespace std; const int m = 1e9 + 7; class Solution { public: int numPermsDISequence(string S) { int n = S.size(); vector<vector<int>> dp(n + 1, vector<int>(n + 1)); for (int j = 0; j <= n; j++) dp[0][j] = 1; for (int i = 0; i < n; i++) { if (S[i] == 'I') { for (int j = 0, curr = 0; j < n - i; j++) { curr = (dp[i][j] + curr) % m; dp[i + 1][j] = (dp[i + 1][j] + curr) % m; } } else { for (int j = n - i - 1, curr = 0; j >= 0; j--) { curr = (dp[i][j + 1] + curr) % m; dp[i + 1][j] = (dp[i + 1][j] + curr) % m; } } } return dp[n][0]; } }; main(){ Solution ob; cout << (ob.numPermsDISequence("IDD")); }
Đầu vào
"IDD"
Đầu ra
3