Longest subsequence with a given OR value : Dynamic Programming Approach

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++

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# 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

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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

chevron_right


Output:

3

Time Complexity: O(N * maxArr) where maxArr is the maximum element from the array.



My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.