Étant donné deux tableaux UN et B de longueur Ntrouver la longueur maximale d’un intervalle commun de A et B tel que le OU au niveau du bit des éléments dans l’intervalle de A est égal à le ET au niveau du bit des éléments dans l’intervalle de B.
Formellement, étant donné les indices i et j (0 ≤ i ≤ j < N), trouver la valeur maximale de j-i+1 tel que: (UN[i] OU UN[i+1] OU … OU UN[j]) = (B[i] ET B[i+1] ET … ET B[j])
Exemples:
Saisir: UN[] = {2, 1, 3, 3}, B[] = {15, 3, 7, 11}
Sortir: 4
Explication: OU(2, 1) = ET(15, 3), Longueur = 2,
OU(2, 1, 3, ) = ET(15, 3, 7), Longueur = 3,
OU(2, 1, 3, 3) = ET(15, 3, 7, 11), Longueur = 4,
OU(1, 3) = ET(3, 7), Longueur = 2,
OU(1, 3, 3) = ET(3, 7, 11), Longueur = 3, etc. La plus grande longueur est donc 4.Saisir: UN[] = {1, 2, 3, 4}, B[] = {4, 3, 7, 11}
Sortir: 2
Explication: OU(2, 3) = ET(3, 7), Longueur = 2, La plus grande longueur de sous-tableau est 2.
Approche: Le problème donné peut être résolu sur la base de l’observation suivante suivie de la recherche binaire :
- Bitwise AND diminuera ou restera le même en prenant continuellement AND avec des éléments.
- Alors que Bitwise OR augmentera ou restera le même en prenant continuellement OR avec des éléments.
Ces propriétés ci-dessus créeront une monotonie afin que nous puissions utiliser la recherche binaire pour calculer la plus grande longueur.
Suivez les étapes ci-dessous pour résoudre le problème :
- Créez un tableau de somme de préfixes 2D pour chaque bit des deux tableaux. Avec ce pré-calcul, nous pouvons calculer OU et ET au niveau du bit en temps presque constant.
- Ensuite, pour chaque index, nous utilisons la recherche binaire où low est égal à zéro et high sera la longueur de l’index i au dernier index.
- Si OR de longueur mid commençant par l’indice i est inférieur ou égal à AND de longueur mid, alors low est réglé sur mid sinon high est réglé sur mid-1.
- Après avoir calculé la plus grande longueur à chaque index avec la condition ci-dessus en utilisant la recherche binaire, nous prenons maximum avec répond qui sera notre réponse.
Vous trouverez ci-dessous la mise en œuvre de l’approche ci-dessus :
C++
// C++ implementation to find the largest length sub-array // of two arrays A and B such that bitwise-OR of A from // index i to j and bitwise-AND of array B from index i to j // are equal #include <bits/stdc++.h> using namespace std; // function for calculating bitwise OR of length 'length' // from index i int orCalculate(int st, int length, vector<vector<int> >& bitPrefix) { int val = 0; for (int j = 0; j < 32; j++) { int cnt = bitPrefix[st + length][j] - bitPrefix[st][j]; if (cnt != 0) // If atleast one jth bit is set // between that range, it will // be added to val val += (1 << j); } return val; } // Function for calculating bitwise AND // of length 'length' from index i int andCalculate(int st, int length, vector<vector<int> >& bitPrefix) { int val = 0; for (int j = 0; j < 32; j++) { int cnt = bitPrefix[st + length][j] - bitPrefix[st][j]; if (cnt == length) // if jth bit is set in all // elements of that range, it // will be added to val val += (1 << j); } return val; } // Function for calculating largest length // sub-array of two arrays A and B such // that bitwise-OR of A from index i to j // and bitwise-AND of array B from index // i to j are equal int largestLength(vector<int>& A, vector<int>& B) { int N = A.size(); // Creating 2D vectors for prefix // bit's sum for both arrays vector<vector<int> > prefixBitSumA(N + 1, vector<int>(32, 0)), prefixBitSumB(N + 1, vector<int>(32, 0)); for (int i = 0; i < N; i++) { for (int j = 0; j < 32; j++) { prefixBitSumA[i + 1][j] = ((A[i] & 1 << j) ? 1 : 0) + prefixBitSumA[i][j]; prefixBitSumB[i + 1][j] = ((B[i] & 1 << j) ? 1 : 0) + prefixBitSumB[i][j]; } } // Initializing ans variable // for storing answer int ans = 0; for (int i = 0; i < N; i++) { int low = 0, high = N - i; // Binary search while loop while (low < high) { int mid = (low + high + 1) / 2; if (orCalculate(i, mid, prefixBitSumA) <= andCalculate(i, mid, prefixBitSumB)) low = mid; // Condition mentioned above else high = mid - 1; } // If final result for this index // 'low' also satisfying problem's // condition then take max with 'ans' // otherwise 'low' is not // considered as result if (orCalculate(i, low, prefixBitSumA) == andCalculate(i, low, prefixBitSumB)) ans = max(ans, low); } // Final answer return ans; } // Driver code int main() { vector<int> A = { 2, 1, 3, 3 }; vector<int> B = { 15, 3, 7, 11 }; // Function Call cout << largestLength(A, B); return 0; }
Complexité temporelle : O(N*logN), où N est la longueur du tableau (logN pour une recherche binaire pour chaque index),
Espace Auxiliaire : O(N), O(N*32*2) pour un préfixe BitArray 2D égal à O(N).