統計將字串拆分為以偶數數字開頭且最小長度為M的K個子字串的方法數
在這個問題中,我們將統計將給定字串劃分為K個子字串的方法數,這些子字串符合問題陳述中給出的條件。
我們將使用遞迴來解決這個問題。此外,我們將使用表格動態規劃方法來有效地解決這個問題。
問題陳述 - 我們給定一個名為bin_Str的特定長度的字串。該字串僅包含從'0'到'9'的數字。我們需要統計將字串劃分為K個子字串的方法數,這些子字串符合以下條件。
子字串至少應包含2個字元。
每個子字串的第一個字元應為偶數數字,最後一個字元應為奇數數字。
示例
輸入
M = 2, K = 2; bin_str = "255687"
輸出
1
解釋 - 根據問題陳述的條件,我們只能將給定字串劃分為255 | 687。
輸入
M = 2, K = 2; bin_str = "26862";
輸出
0
解釋 - 由於字串只包含偶數數字,因此我們無法將其拆分為2個子字串,每個子字串都以奇數數字結尾。
輸入
M = 2, K = 3; bin_str = "856549867";
輸出
3
解釋 -可能的劃分方法有85|65|49867、8565|49|867和85|6549|867。
方法一
我們將使用遞迴函式來解決此方法中的問題。如果我們在當前索引處找到有效的子字串,我們將進行遞迴呼叫以統計將剩餘子字串劃分為K-1個子字串的方法數。
演算法
步驟1 - 獲取給定字串的首字元和尾字元。
步驟2 - 如果首字元不是偶數且尾字元不是奇數,則返回0。
步驟3 - 如果起始索引等於字串長度,則返回0,因為我們到達了給定字串的末尾。
步驟4 - 如果K == 1,則取字串長度和起始索引的差值。如果它等於或大於M,則返回1。否則,返回0。在這裡,我們需要獲取剩餘的子字串,如果K為1。
步驟5 - 將'ops'初始化為'0'以儲存劃分方法的數量,將'len'初始化為'0'以儲存當前子字串的長度。
步驟6 - 從'start'索引開始遍歷字串到字串的末尾。
步驟7 - 將'len'加1。此外,獲取當前字元和下一個字元。
步驟8 - 如果'len'大於M,當前數字是奇數,下一個數字是偶數,我們可以在當前索引處結束劃分。因此,透過傳遞下一個索引和K-1作為函式引數來進行countWays()函式的遞迴呼叫。
步驟9 - 最後,返回'ops'值。
示例
#include <bits/stdc++.h> using namespace std; int countWays(int start, int str_len, int K, int M, string bin_str) { // Geeting first and last character of the substring int f_char = bin_str[0] - '0'; int l_char = bin_str[str_len - 1] - '0'; if (f_char % 2 != 0 || l_char % 2 != 1) { return 0; } // When we reach at the end if (start == str_len) return 0; // Base case if (K == 1) { int chars = str_len - start; // Validate minimum length of substring if (chars >= M) return 1; return 0; } int ops = 0; int len = 0; // Traverse all partions for (int p = start; p < str_len - 1; p++) { len++; int first = bin_str[p] - '0'; int second = bin_str[p + 1] - '0'; // If we can end the partition at p and start a new partition at p+1 if (len >= M && first % 2 == 1) { if (second % 2 == 0) { ops += countWays(p + 1, str_len, K - 1, M, bin_str); } } } return ops; } int main() { int M = 2, K = 2; string bin_str = "255687"; int str_len = bin_str.length(); cout << "The number of ways to split the string is " << countWays(0, str_len, K, M, bin_str) << endl; return 0; }
輸出
The number of ways to split the string is 1
拆分字串的方法數為1
空間複雜度 - O(1),因為我們不使用額外的空間。
方法二
在此方法中,我們將使用表格動態規劃技術來統計將字串劃分為K個分割槽的數量。我們將使用矩陣來儲存先前狀態的輸出。
演算法
步驟1 - 定義大小為1001 x 1001的全域性矩陣[]陣列。矩陣行對映到字串字元,矩陣列對映到K。
步驟2 - 獲取字串的首字元和尾字元。如果首字元為偶數且尾字元為奇數,則執行countWays()函式。否則,在輸出中列印0。
步驟3 - 在countWays函式中,初始化矩陣[]陣列。
步驟4 - 遍歷等於字串長度的行和等於K的列的矩陣。如果行等於字串長度,則將整行更新為0。
步驟5 - 否則,如果q為1,並且字串長度-當前索引大於M,則將陣列matrix[p][q]初始化為1。否則,將matrix[p][q]初始化為0。
步驟6 - 在其他情況下,將matrix[p][q]初始化為-1。
步驟7 - 使用兩個巢狀迴圈填充矩陣。使用外迴圈進行2到K的遍歷,使用內迴圈進行0到字串長度的遍歷。
步驟8 - 將'ops'和'len'初始化為0。此外,從第p個索引開始遍歷字串,在每次迭代中將'len'加1。
步驟9 - 獲取字串的當前字元和下一個字元。
步驟10 - 如果長度大於M,當前字元為奇數,下一個字元為偶數,則將matrix[k + 1][q − 1]新增到'ops'。
步驟11 - 將matrix[p][q]更新為'ops'。
步驟12 - 最後返回matrix[0][k]。
示例
#include <bits/stdc++.h> using namespace std; int matrix[1001][1001]; int countWays(int str_len, int K, int M, string bin_str) { // Base case for (int p = 0; p <= str_len; p++) { for (int q = 0; q <= K; q++) { // When index points to end index of string if (p == str_len) matrix[p][q] = 0; else if (q == 1) { // When only 1 split needs to be done int chars = str_len - p; // Validating substring's minimum len if (chars >= M) matrix[p][q] = 1; else matrix[p][q] = 0; } else { // For other cases matrix[p][q] = -1; } } } // Dynamic programming approach for (int q = 2; q <= K; q++) { for (int p = 0; p < str_len; p++) { int ops = 0; int len = 0; // length of current substring for (int k = p; k < str_len - 1; k++) { len++; int first = bin_str[k] - '0'; int second = bin_str[k + 1] - '0'; // Validate condition for split if (len >= M && first % 2 == 1 && second % 2 == 0) { // Substring starting from k + 1 index needs to be splited in q-1 parts ops += matrix[k + 1][q - 1]; } } matrix[p][q] = ops; } } return matrix[0][K]; } int main() { int M = 2, K = 2; string bin_str = "255687"; int str_len = bin_str.length(); int f_char = bin_str[0] - '0'; int l_char = bin_str[str_len - 1] - '0'; cout << "The number of ways to split the string is "; if (f_char % 2 != 0 || l_char % 2 != 1) { cout << 0 << endl; } else { cout << countWays(str_len, K, M, bin_str) << endl; } return 0; }
輸出
The number of ways to split the string is 1
時間複雜度 - O(N*N*K),其中O(N*N)用於查詢所有子字串,O(K)用於K個分割槽。
空間複雜度 - O(N*K) 用於使用矩陣[]陣列。