Given two arrays arr[] and arr1[] of lengths N and M respectively, the task is to find the longest increasing subsequence of array arr[] such that it does not contain array arr1[] as subarray.
Examples:
Input: arr[] = {5, 3, 9, 3, 4, 7}, arr1[] = {3, 3, 7}
Output: 4
Explanation: Required longest increasing subsequence is {3, 3, 4, 7}.
Input: arr[] = {1, 2, 3}, arr1[] = {1, 2, 3}
Output: 2
Explanation: Required longest increasing subsequence is {1, 2}.
Naive Approach: The simplest approach is to generate all possible subsequences of the given array and print the length of the longest subsequence among them, which does not contain arr1[] as subarray.
Time Complexity: O(M * 2N) where N and M are the lengths of the given arrays.
Auxiliary Space: O(M + N)
Efficient Approach: The idea is to use lps[] array generated using KMP Algorithm and Dynamic Programming to find the longest non-decreasing subsequence without any subarray equals to sequence[]. Follow the below steps to solve the problem:
- Initialize an array dp[N][N][N] where dp[i][j][K] stores the maximum length of non-decreasing subsequence up to index i where j is the index of the previously chosen element in the array arr[] and K denotes that the currently found sequence contains subarray sequence[0, K].
- Also, generate an array to store the length of the longest prefix suffix using KMP Algorithm.
- The maximum length can be found by memoizing the below dp transitions:
dp(i, prev, k) = max(1 + dp(i + 1, i, k2), dp(i + 1, prev, k)) where,
- i is the current index.
- prev is the previously chosen element.
- k2 is index of prefix subarray included so far in the currently found sequence which can be found using KMP Array for longest prefix suffix.
Base Case:
- If k is equals to the length of the given sequence, return as the currently found subsequence contains the arr1[].
- If i reaches N, return as no more elements exist.
- If the current state has already been calculated, return.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int dp[6][6][6];
int KMPArray[2];
int m;
int findSubsequence( int a[], int sequence[], int i,
int prev, int k, int al, int sl)
{
if (k == m)
return INT_MIN;
if (i == al)
return 0;
if (prev != -1 && dp[i][prev][k] != -1) {
return dp[i][prev][k];
}
int include = 0;
if (prev == -1 || a[i] >= a[prev]) {
int k2 = k;
while (k2 > 0
&& a[i] != sequence[k2])
k2 = KMPArray[k2 - 1];
if (a[i] == sequence[k2])
k2++;
include = 1
+ findSubsequence(
a, sequence,
i + 1, i, k2, al, sl);
}
int ans = max(
include, findSubsequence(
a, sequence,
i + 1, prev, k, al, sl));
if (prev != -1) {
dp[i][prev][k] = ans;
}
return ans;
}
void fillKMPArray( int pattern[])
{
int j = 0;
int i = 1;
KMPArray[0] = 0;
while (i < m) {
if (pattern[i] == pattern[j]) {
j++;
KMPArray[i] = j;
i++;
}
else {
if (j != 0)
j = KMPArray[j - 1];
else {
KMPArray[i] = j;
i++;
}
}
}
}
void printAnswer( int a[], int sequence[], int al, int sl)
{
m = sl;
fillKMPArray(sequence);
memset (dp, -1, sizeof (dp));
int ans = findSubsequence(a, sequence, 0, -1, 0, al, sl);
cout << ((ans < 0) ? 0 : ans) << endl;
}
int main()
{
int arr[] = { 5, 3, 9, 3, 4, 7 };
int arr1[] = { 3, 4 };
printAnswer(arr, arr1, 6, 2);
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
static int [][][] dp;
static int [] KMPArray;
static int m;
private static int findSubsequence(
int [] a, int [] sequence,
int i, int prev, int k)
{
if (k == m)
return Integer.MIN_VALUE;
if (i == a.length)
return 0 ;
if (prev != - 1
&& dp[i][prev][k] != - 1 ) {
return dp[i][prev][k];
}
int include = 0 ;
if (prev == - 1 || a[i] >= a[prev]) {
int k2 = k;
while (k2 > 0
&& a[i] != sequence[k2])
k2 = KMPArray[k2 - 1 ];
if (a[i] == sequence[k2])
k2++;
include = 1
+ findSubsequence(
a, sequence,
i + 1 , i, k2);
}
int ans = Math.max(
include, findSubsequence(
a, sequence,
i + 1 , prev, k));
if (prev != - 1 ) {
dp[i][prev][k] = ans;
}
return ans;
}
private static void
fillKMPArray( int [] pattern)
{
int j = 0 ;
int i = 1 ;
KMPArray[ 0 ] = 0 ;
while (i < m) {
if (pattern[i] == pattern[j]) {
j++;
KMPArray[i] = j;
i++;
}
else {
if (j != 0 )
j = KMPArray[j - 1 ];
else {
KMPArray[i] = j;
i++;
}
}
}
}
static void printAnswer(
int a[], int sequence[])
{
m = sequence.length;
KMPArray = new int [m];
fillKMPArray(sequence);
dp = new int [a.length][a.length][a.length];
for ( int i = 0 ; i < a.length; i++)
for ( int j = 0 ; j < a.length; j++)
Arrays.fill(dp[i][j], - 1 );
int ans = findSubsequence(
a, sequence, 0 , - 1 , 0 );
System.out.println((ans < 0 ) ? 0 : ans);
}
public static void
main(String[] args) throws Exception
{
int [] arr = { 5 , 3 , 9 , 3 , 4 , 7 };
int [] arr1 = { 3 , 4 };
printAnswer(arr, arr1);
}
}
|
Python3
from pickle import GLOBAL
import sys
dp = [[[ - 1 for i in range ( 6 )] for j in range ( 6 )] for k in range ( 6 )]
KMPArray = [ 0 for i in range ( 2 )]
m = 0
def findSubsequence(a, sequence, i,prev, k, al, sl):
global KMPArray
global dp
if (k = = m):
return - sys.maxsize - 1
if (i = = al):
return 0
if (prev ! = - 1 and dp[i][prev][k] ! = - 1 ):
return dp[i][prev][k]
include = 0
if (prev = = - 1 or a[i] > = a[prev]):
k2 = k
while (k2 > 0
and a[i] ! = sequence[k2]):
k2 = KMPArray[k2 - 1 ]
if (a[i] = = sequence[k2]):
k2 + = 1
include = 1 + findSubsequence(
a, sequence,
i + 1 , i, k2, al, sl)
ans = max (include, findSubsequence(
a, sequence,
i + 1 , prev, k, al, sl))
if (prev ! = - 1 ) :
dp[i][prev][k] = ans
return ans
def fillKMPArray(pattern):
global m
global KMPArray
j = 0
i = 1
KMPArray[ 0 ] = 0
while (i < m):
if (pattern[i] = = pattern[j]):
j + = 1
KMPArray[i] = j
i + = 1
else :
if (j ! = 0 ):
j = KMPArray[j - 1 ]
else :
KMPArray[i] = j
i + = 1
def printAnswer(a, sequence, al, sl):
global m
m = sl
fillKMPArray(sequence)
ans = findSubsequence(a, sequence, 0 , - 1 , 0 , al, sl)
if (ans < 0 ):
print ( 0 )
else :
print (ans)
arr = [ 5 , 3 , 9 , 3 , 4 , 7 ]
arr1 = [ 3 , 4 ]
printAnswer(arr, arr1, 6 , 2 )
|
C#
using System;
using System.Collections;
using System.Collections.Generic;
class GFG{
static int [,,] dp;
static int [] KMPArray;
static int m;
private static int findSubsequence( int [] a,
int [] sequence,
int i, int prev,
int k)
{
if (k == m)
return int .MinValue;
if (i == a.Length)
return 0;
if (prev != -1 && dp[i, prev, k] != -1)
{
return dp[i, prev, k];
}
int include = 0;
if (prev == -1 || a[i] >= a[prev])
{
int k2 = k;
while (k2 > 0 && a[i] != sequence[k2])
k2 = KMPArray[k2 - 1];
if (a[i] == sequence[k2])
k2++;
include = 1 + findSubsequence(a, sequence,
i + 1, i, k2);
}
int ans = Math.Max(include,
findSubsequence(a, sequence,
i + 1, prev, k));
if (prev != -1)
{
dp[i, prev, k] = ans;
}
return ans;
}
private static void fillKMPArray( int [] pattern)
{
int j = 0;
int i = 1;
KMPArray[0] = 0;
while (i < m)
{
if (pattern[i] == pattern[j])
{
j++;
KMPArray[i] = j;
i++;
}
else
{
if (j != 0)
j = KMPArray[j - 1];
else
{
KMPArray[i] = j;
i++;
}
}
}
}
static void printAnswer( int [] a, int [] sequence)
{
m = sequence.Length;
KMPArray = new int [m];
fillKMPArray(sequence);
dp = new int [a.Length, a.Length, a.Length];
for ( int i = 0; i < a.Length; i++)
for ( int j = 0; j < a.Length; j++)
for ( int k = 0; k < a.Length; k++)
dp[i, j, k] = -1;
int ans = findSubsequence(a, sequence, 0, -1, 0);
Console.WriteLine((ans < 0) ? 0 : ans);
}
public static void Main()
{
int [] arr = { 5, 3, 9, 3, 4, 7 };
int [] arr1 = { 3, 4 };
printAnswer(arr, arr1);
}
}
|
Javascript
<script>
let dp = new Array(6).fill(-1).map(()=> new Array(6).fill(-1).map(()=> new Array(6).fill(-1)));
let KMPArray = new Array(2);
let m;
function findSubsequence(a, sequence, i,prev, k, al, sl)
{
if (k == m)
return Number.MIN_VALUE;
if (i == al)
return 0;
if (prev != -1 && dp[i][prev][k] != -1) {
return dp[i][prev][k];
}
let include = 0;
if (prev == -1 || a[i] >= a[prev]) {
let k2 = k;
while (k2 > 0
&& a[i] != sequence[k2])
k2 = KMPArray[k2 - 1];
if (a[i] == sequence[k2])
k2++;
include = 1
+ findSubsequence(
a, sequence,
i + 1, i, k2, al, sl);
}
let ans = Math.max(
include, findSubsequence(
a, sequence,
i + 1, prev, k, al, sl));
if (prev != -1) {
dp[i][prev][k] = ans;
}
return ans;
}
function fillKMPArray(pattern)
{
let j = 0;
let i = 1;
KMPArray[0] = 0;
while (i < m) {
if (pattern[i] == pattern[j]) {
j++;
KMPArray[i] = j;
i++;
}
else {
if (j != 0)
j = KMPArray[j - 1];
else {
KMPArray[i] = j;
i++;
}
}
}
}
function printAnswer(a, sequence, al, sl)
{
m = sl;
fillKMPArray(sequence);
let ans = findSubsequence(a, sequence, 0, -1, 0, al, sl);
console.log((ans < 0) ? 0 : ans);
}
let arr = [ 5, 3, 9, 3, 4, 7 ];
let arr1 = [ 3, 4 ];
printAnswer(arr, arr1, 6, 2);
</script>
|
Time Complexity: O(N3)
Auxiliary Space: O(N3)
Related Topic: Subarrays, Subsequences, and Subsets in Array
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!