문자열 S가 있다고 가정합니다. 이것은 {'D', 'I'} 집합의 문자 문자열입니다. (D는 "감소"를 의미하고 I는 "증가"를 의미)
이제 유효한 순열이 모든 i에 대해 다음 규칙을 충족하도록 정수 {0 ~ n}의 순열 P[0], P[1], ..., P[n]이라고 가정합니다.
-
S[i] =='D'인 경우 P[i]> P[i+1];
-
그렇지 않으면 S[i] =='I'일 때 P[i]
유효한 순열이 몇 개나 있는지 찾아야 합니까? 답변이 매우 클 수 있으므로 mod 10^9 + 7을 사용하여 반환합니다.
따라서 입력이 "IDD"와 같으면 출력은 3이 됩니다. 따라서 (0,3,2,1), (1,3,2,0), ( 2,3,1,0).
이 문제를 해결하기 위해 다음 단계를 따릅니다. −
-
n :=S
의 크기 -
(n + 1) x (n + 1) 크기의 2D 배열 dp 하나 정의
-
초기화 j :=0의 경우 j <=n일 때 업데이트(j를 1만큼 증가), −
-
dp[0, j] :=1
-
-
initialize i :=0의 경우, i
-
S[i]가 'I'와 같으면 -
-
초기화 j :=0, curr :=0, j
-
curr :=(dp[i, j] + curr) 모드 m
-
dp[i + 1, j] =(dp[i + 1, j] + curr)
-
-
-
그렇지 않으면
-
j를 초기화하기 위해 :=n - i - 1, curr :=0, j>=0일 때 업데이트(j를 1만큼 감소), −
-
curr :=(dp[i, j + 1] + curr) 모드 m
-
dp[i + 1, j] =(dp[i + 1, j] + curr)
-
-
-
-
반환 dp[n, 0]
이해를 돕기 위해 다음 구현을 살펴보겠습니다. −
예시
#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")); }
입력
"IDD"
출력
3