Given an array arr[], the task is to find the longest subsequence with a given OR value M. If there is no such sub-sequence then print 0.
Examples:
Input: arr[] = {3, 7, 2, 3}, M = 3
Output: 3
{3, 2, 3} is the required subsequence
3 | 2 | 3 = 3
Input: arr[] = {2, 2}, M = 3
Output: 0
Approach: A simple solution is to generate all the possible sub-sequences and then find the largest among them with the required OR value. However, for smaller values of M, a dynamic programming approach can be used.
Let’s look at the recurrence relation first.
dp[i][curr_or] = max(dp[i + 1][curr_or], dp[i + 1][curr_or | arr[i]] + 1)
Let’s understand the states of DP now. Here, dp[i][curr_or] stores the longest subsequence of the subarray arr[i…N-1] such the curr_or gives M when gets ORed with this subsequence. At each step, either choose the index i and update curr_or or reject index i and continue.
Below is the implementation of the above approach:
C++
// C++ implementation of the approach #include <bits/stdc++.h> using namespace std; #define maxN 20 #define maxM 64 // To store the states of DP int dp[maxN][maxM]; bool v[maxN][maxM]; // Function to return the required length int findLen( int * arr, int i, int curr, int n, int m) { // Base case if (i == n) { if (curr == m) return 0; else return -1; } // If the state has been solved before // return the value of the state if (v[i][curr]) return dp[i][curr]; // Setting the state as solved v[i][curr] = 1; // Recurrence relation int l = findLen(arr, i + 1, curr, n, m); int r = findLen(arr, i + 1, curr | arr[i], n, m); dp[i][curr] = l; if (r != -1) dp[i][curr] = max(dp[i][curr], r + 1); return dp[i][curr]; } // Driver code int main() { int arr[] = { 3, 7, 2, 3 }; int n = sizeof (arr) / sizeof ( int ); int m = 3; int ans = findLen(arr, 0, 0, n, m); if (ans == -1) cout << 0; else cout << ans; return 0; } |
Java
// Java implementation of the approach class GFG { static int maxN = 20 ; static int maxM = 64 ; // To store the states of DP static int [][]dp = new int [maxN][maxM]; static boolean [][]v = new boolean [maxN][maxM]; // Function to return the required length static int findLen( int [] arr, int i, int curr, int n, int m) { // Base case if (i == n) { if (curr == m) return 0 ; else return - 1 ; } // If the state has been solved before // return the value of the state if (v[i][curr]) return dp[i][curr]; // Setting the state as solved v[i][curr] = true ; // Recurrence relation int l = findLen(arr, i + 1 , curr, n, m); int r = findLen(arr, i + 1 , curr | arr[i], n, m); dp[i][curr] = l; if (r != - 1 ) dp[i][curr] = Math.max(dp[i][curr], r + 1 ); return dp[i][curr]; } // Driver code public static void main(String []args) { int arr[] = { 3 , 7 , 2 , 3 }; int n = arr.length; int m = 3 ; int ans = findLen(arr, 0 , 0 , n, m); if (ans == - 1 ) System.out.println( 0 ); else System.out.println(ans); } } // This code is contributed by 29AjayKumar |
Python3
# Python3 implementation of the approach import numpy as np maxN = 20 maxM = 64 # To store the states of DP dp = np.zeros((maxN, maxM)); v = np.zeros((maxN, maxM)); # Function to return the required length def findLen(arr, i, curr, n, m) : # Base case if (i = = n) : if (curr = = m) : return 0 ; else : return - 1 ; # If the state has been solved before # return the value of the state if (v[i][curr]) : return dp[i][curr]; # Setting the state as solved v[i][curr] = 1 ; # Recurrence relation l = findLen(arr, i + 1 , curr, n, m); r = findLen(arr, i + 1 , curr | arr[i], n, m); dp[i][curr] = l; if (r ! = - 1 ) : dp[i][curr] = max (dp[i][curr], r + 1 ); return dp[i][curr]; # Driver code if __name__ = = "__main__" : arr = [ 3 , 7 , 2 , 3 ]; n = len (arr); m = 3 ; ans = findLen(arr, 0 , 0 , n, m); if (ans = = - 1 ) : print ( 0 ); else : print (ans); # This code is contributed by AnkitRai01 |
C#
// C# implementation of the approach using System; class GFG { static int maxN = 20; static int maxM = 64; // To store the states of DP static int [,]dp = new int [maxN,maxM]; static bool [,]v = new bool [maxN,maxM]; // Function to return the required length static int findLen( int [] arr, int i, int curr, int n, int m) { // Base case if (i == n) { if (curr == m) return 0; else return -1; } // If the state has been solved before // return the value of the state if (v[i,curr]) return dp[i,curr]; // Setting the state as solved v[i,curr] = true ; // Recurrence relation int l = findLen(arr, i + 1, curr, n, m); int r = findLen(arr, i + 1, curr | arr[i], n, m); dp[i,curr] = l; if (r != -1) dp[i,curr] = Math.Max(dp[i,curr], r + 1); return dp[i,curr]; } // Driver code public static void Main(String []args) { int []arr = { 3, 7, 2, 3 }; int n = arr.Length; int m = 3; int ans = findLen(arr, 0, 0, n, m); if (ans == -1) Console.WriteLine(0); else Console.WriteLine(ans); } } // This code is contributed by PrinciRaj1992 |
Javascript
<script> // Javascript implementation of the approach var maxN = 20 var maxM = 64 // To store the states of DP var dp = Array.from(Array(maxN), ()=> Array(maxM)); var v = Array.from(Array(maxN), ()=> Array(maxM)); // Function to return the required length function findLen(arr, i, curr, n, m) { // Base case if (i == n) { if (curr == m) return 0; else return -1; } // If the state has been solved before // return the value of the state if (v[i][curr]) return dp[i][curr]; // Setting the state as solved v[i][curr] = 1; // Recurrence relation var l = findLen(arr, i + 1, curr, n, m); var r = findLen(arr, i + 1, curr | arr[i], n, m); dp[i][curr] = l; if (r != -1) dp[i][curr] = Math.max(dp[i][curr], r + 1); return dp[i][curr]; } // Driver code var arr = [3, 7, 2, 3]; var n = arr.length; var m = 3; var ans = findLen(arr, 0, 0, n, m); if (ans == -1) document.write( 0); else document.write( ans); </script> |
3
Time Complexity: O(N * maxArr) where maxArr is the maximum element from the array.
Auxiliary Space: O(maxN * maxM)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!