ধরুন আমাদের একটি স্ট্রিং S আছে। এটি {'D', 'I'} সেট থেকে অক্ষরের একটি স্ট্রিং। (D মানে "হ্রাস" এবং আমার মানে "বাড়ছে")
এখন বিবেচনা করুন একটি বৈধ স্থানচ্যুতি হল P[0], P[1], ..., P[n] পূর্ণসংখ্যার {0 থেকে n}, যাতে সকল i জন্য, এটি এই নিয়মগুলি পূরণ করে:
-
যদি S[i] =='D', তাহলে P[i]> P[i+1];
-
অন্যথায় যখন S[i] =='I', তখন P[i]
আমাদের খুঁজে বের করতে হবে কত বৈধ পারমুটেশন আছে? উত্তরটি অনেক বড় হতে পারে, তাই আমরা মোড 10^9 + 7 ব্যবহার করে ফিরে আসব।
সুতরাং, যদি ইনপুটটি "IDD" এর মতো হয়, তাহলে আউটপুট হবে 3, তাই তিনটি ভিন্ন স্থানান্তর হবে, এগুলো হল (0,3,2,1), (1,3,2,0), ( 2,3,1,0)।
এটি সমাধান করতে, আমরা এই পদক্ষেপগুলি অনুসরণ করব -
-
n :=S
এর আকার -
একটি 2D অ্যারে ডিপি আকারের (n + 1) x (n + 1) সংজ্ঞায়িত করুন
-
আরম্ভ করার জন্য j :=0, যখন j <=n, আপডেট করুন (j 1 দ্বারা বৃদ্ধি করুন), করুন −
-
dp[0, j] :=1
-
-
আরম্ভ করার জন্য i :=0, যখন i
-
যদি S[i] 'I' এর মত হয়, তাহলে −
-
আরম্ভ করার জন্য j :=0, curr :=0, যখন j
-
curr :=(dp[i, j] + curr) mod 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) mod 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