C ++中DI序列的有效排列
假设我们有一个字符串S。这是一组{'D','I'}中的字符串。(D表示“减少”,而我的意思是“增加”)
现在考虑一个有效的排列是整数{0到n}的排列P[0],P[1],...,P[n],这样对于所有i,它都满足以下规则:
如果S[i]=='D',则P[i]>P[i+1];
否则,当S[i]=='I'时,则P[i]<P[i+1]。
我们必须找到多少个有效排列?答案可能非常大,因此我们将使用mod10^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
对于初始化i:=0,当i<n时,更新(将i增加1),执行-
对于初始化j:=n-i-1,curr:=0,当j>=0时,更新(将j减1),-
curr:=(dp[i,j+1]+curr)modm
dp[i+1,j]=(dp[i+1,j]+curr)
对于初始化j:=0,curr:=0,当j<n-i时,更新(j增加1),-
curr:=(dp[i,j]+curr)modm
dp[i+1,j]=(dp[i+1,j]+curr)
如果S[i]与“I”相同,则-
除此以外
返回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