Related Articles

# Length of the longest increasing subsequence which does not contain a given sequence as Subarray

• Difficulty Level : Medium
• Last Updated : 01 Mar, 2021

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:

1. 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].
2. Also, generate an array to store the length of the longest prefix suffix using KMP Algorithm.
3. 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++

 `// C++ program for the above approach``#include ``using` `namespace` `std;` `// Initialize dp and KMP array``int` `dp;``int` `KMPArray;` `// Length of the given sequence[]``int` `m;` `// Function to find the max-length``// subsequence that does not have``// subarray sequence[]``int` `findSubsequence(``int` `a[], ``int` `sequence[], ``int` `i,``                    ``int` `prev, ``int` `k, ``int` `al, ``int` `sl)``{``    ``// Stores the subsequence``    ``// explored so far``    ``if` `(k == m)``        ``return` `INT_MIN;` `    ``// Base Case``    ``if` `(i == al)``        ``return` `0;` `    ``// Using memoization to``    ``// avoid re-computation``    ``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;` `        ``// Using KMP array to find``        ``// corresponding index in arr1[]``        ``while` `(k2 > 0``               ``&& a[i] != sequence[k2])``            ``k2 = KMPArray[k2 - 1];` `        ``// Incrementing k2 as we are``        ``// including this element in``        ``// the subsequence``        ``if` `(a[i] == sequence[k2])``            ``k2++;` `        ``// Possible answer for``        ``// current state``        ``include = 1``                  ``+ findSubsequence(``                        ``a, sequence,``                        ``i + 1, i, k2, al, sl);``    ``}` `    ``// Maximum answer for``    ``// current state``    ``int` `ans = max(``        ``include, findSubsequence(``                     ``a, sequence,``                     ``i + 1, prev, k, al, sl));` `    ``// Memoizing the answer for``    ``// the corresponding state``    ``if` `(prev != -1) {``        ``dp[i][prev][k] = ans;``    ``}` `    ``// Return the answer for``    ``// current state``    ``return` `ans;``}` `// Function that generate KMP Array``void` `fillKMPArray(``int` `pattern[])``{``  ` `    ``// Previous longest prefix suffix``    ``int` `j = 0;` `    ``int` `i = 1;` `    ``// KMPArray is a always 0``    ``KMPArray = 0;` `    ``// The loop calculates KMPArray[i]``    ``// for i = 1 to M - 1``    ``while` `(i < m) {` `        ``// If current character is``        ``// same``        ``if` `(pattern[i] == pattern[j]) {``            ``j++;` `            ``// Update the KMP array``            ``KMPArray[i] = j;``            ``i++;``        ``}` `        ``// Otherwise``        ``else` `{` `            ``// Update the KMP array``            ``if` `(j != 0)``                ``j = KMPArray[j - 1];``            ``else` `{``                ``KMPArray[i] = j;``                ``i++;``            ``}``        ``}``    ``}``}` `// Function to print the maximum``// possible length``void` `printAnswer(``int` `a[], ``int` `sequence[], ``int` `al, ``int` `sl)``{` `    ``// Length of the given sequence``    ``m = sl;` `    ``// Generate KMP array``    ``fillKMPArray(sequence);` `    `  `    ``// Initialize the states to -1``    ``memset``(dp, -1, ``sizeof``(dp));` `    ``// Get answer``    ``int` `ans = findSubsequence(a, sequence, 0, -1, 0, al, sl);` `    ``// Print answer``    ``cout << ((ans < 0) ? 0 : ans) << endl;``}``    ` `// Driver code``int` `main()``{``  ` `    ``// Given array``    ``int` `arr[] = { 5, 3, 9, 3, 4, 7 };` `    ``// Give arr1``    ``int` `arr1[] = { 3, 4 };` `    ``// Function Call``    ``printAnswer(arr, arr1, 6, 2);``    ``return` `0;``}` `// This code is contributed by divyeshrabadiya07.`

## Java

 `// Java program for the above approach` `import` `java.io.*;``import` `java.util.*;` `class` `GFG {` `    ``// Initialize dp and KMP array``    ``static` `int``[][][] dp;``    ``static` `int``[] KMPArray;` `    ``// Length of the given sequence[]``    ``static` `int` `m;` `    ``// Function to find the max-length``    ``// subsequence that does not have``    ``// subarray sequence[]``    ``private` `static` `int` `findSubsequence(``        ``int``[] a, ``int``[] sequence,``        ``int` `i, ``int` `prev, ``int` `k)``    ``{``        ``// Stores the subsequence``        ``// explored so far``        ``if` `(k == m)``            ``return` `Integer.MIN_VALUE;` `        ``// Base Case``        ``if` `(i == a.length)``            ``return` `0``;` `        ``// Using memoization to``        ``// avoid re-computation``        ``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;` `            ``// Using KMP array to find``            ``// corresponding index in arr1[]``            ``while` `(k2 > ``0``                   ``&& a[i] != sequence[k2])``                ``k2 = KMPArray[k2 - ``1``];` `            ``// Incrementing k2 as we are``            ``// including this element in``            ``// the subsequence``            ``if` `(a[i] == sequence[k2])``                ``k2++;` `            ``// Possible answer for``            ``// current state``            ``include = ``1``                      ``+ findSubsequence(``                            ``a, sequence,``                            ``i + ``1``, i, k2);``        ``}` `        ``// Maximum answer for``        ``// current state``        ``int` `ans = Math.max(``            ``include, findSubsequence(``                         ``a, sequence,``                         ``i + ``1``, prev, k));` `        ``// Memoizing the answer for``        ``// the corresponding state``        ``if` `(prev != -``1``) {``            ``dp[i][prev][k] = ans;``        ``}` `        ``// Return the answer for``        ``// current state``        ``return` `ans;``    ``}` `    ``// Function that generate KMP Array``    ``private` `static` `void``    ``fillKMPArray(``int``[] pattern)``    ``{``        ``// Previous longest prefix suffix``        ``int` `j = ``0``;` `        ``int` `i = ``1``;` `        ``// KMPArray is a always 0``        ``KMPArray[``0``] = ``0``;` `        ``// The loop calculates KMPArray[i]``        ``// for i = 1 to M - 1``        ``while` `(i < m) {` `            ``// If current character is``            ``// same``            ``if` `(pattern[i] == pattern[j]) {``                ``j++;` `                ``// Update the KMP array``                ``KMPArray[i] = j;``                ``i++;``            ``}` `            ``// Otherwise``            ``else` `{` `                ``// Update the KMP array``                ``if` `(j != ``0``)``                    ``j = KMPArray[j - ``1``];``                ``else` `{``                    ``KMPArray[i] = j;``                    ``i++;``                ``}``            ``}``        ``}``    ``}` `    ``// Function to print the maximum``    ``// possible length``    ``static` `void` `printAnswer(``        ``int` `a[], ``int` `sequence[])``    ``{` `        ``// Length of the given sequence``        ``m = sequence.length;` `        ``// Initialize kmp array``        ``KMPArray = ``new` `int``[m];` `        ``// Generate KMP array``        ``fillKMPArray(sequence);` `        ``// Initialize dp``        ``dp = ``new` `int``[a.length][a.length][a.length];` `        ``// Initialize the states to -1``        ``for` `(``int` `i = ``0``; i < a.length; i++)``            ``for` `(``int` `j = ``0``; j < a.length; j++)``                ``Arrays.fill(dp[i][j], -``1``);` `        ``// Get answer``        ``int` `ans = findSubsequence(``            ``a, sequence, ``0``, -``1``, ``0``);` `        ``// Print answer``        ``System.out.println((ans < ``0``) ? ``0` `: ans);``    ``}` `    ``// Driver code``    ``public` `static` `void``        ``main(String[] args) ``throws` `Exception``    ``{``        ``// Given array``        ``int``[] arr = { ``5``, ``3``, ``9``, ``3``, ``4``, ``7` `};` `        ``// Give arr1``        ``int``[] arr1 = { ``3``, ``4` `};` `        ``// Function Call``        ``printAnswer(arr, arr1);``    ``}``}`

## C#

 `// C# program for the above approach``using` `System;``using` `System.Collections;``using` `System.Collections.Generic;` `class` `GFG{` `// Initialize dp and KMP array``static` `int``[,,] dp;``static` `int``[] KMPArray;` `// Length of the given sequence[]``static` `int` `m;` `// Function to find the max-length``// subsequence that does not have``// subarray sequence[]``private` `static` `int` `findSubsequence(``int``[] a,``                                   ``int``[] sequence,``                                   ``int` `i, ``int` `prev,``                                   ``int` `k)``{``    ` `    ``// Stores the subsequence``    ``// explored so far``    ``if` `(k == m)``        ``return` `int``.MinValue;` `    ``// Base Case``    ``if` `(i == a.Length)``        ``return` `0;` `    ``// Using memoization to``    ``// avoid re-computation``    ``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;` `        ``// Using KMP array to find``        ``// corresponding index in arr1[]``        ``while` `(k2 > 0 && a[i] != sequence[k2])``            ``k2 = KMPArray[k2 - 1];` `        ``// Incrementing k2 as we are``        ``// including this element in``        ``// the subsequence``        ``if` `(a[i] == sequence[k2])``            ``k2++;` `        ``// Possible answer for``        ``// current state``        ``include = 1 + findSubsequence(a, sequence,``                                      ``i + 1, i, k2);``    ``}` `    ``// Maximum answer for``    ``// current state``    ``int` `ans = Math.Max(include,``                       ``findSubsequence(a, sequence,``                                       ``i + 1, prev, k));` `    ``// Memoizing the answer for``    ``// the corresponding state``    ``if` `(prev != -1)``    ``{``        ``dp[i, prev, k] = ans;``    ``}` `    ``// Return the answer for``    ``// current state``    ``return` `ans;``}` `// Function that generate KMP Array``private` `static` `void` `fillKMPArray(``int``[] pattern)``{``    ` `    ``// Previous longest prefix suffix``    ``int` `j = 0;` `    ``int` `i = 1;` `    ``// KMPArray is a always 0``    ``KMPArray = 0;` `    ``// The loop calculates KMPArray[i]``    ``// for i = 1 to M - 1``    ``while` `(i < m)``    ``{``        ` `        ``// If current character is``        ``// same``        ``if` `(pattern[i] == pattern[j])``        ``{``            ``j++;` `            ``// Update the KMP array``            ``KMPArray[i] = j;``            ``i++;``        ``}` `        ``// Otherwise``        ``else``        ``{``            ` `            ``// Update the KMP array``            ``if` `(j != 0)``                ``j = KMPArray[j - 1];``            ``else``            ``{``                ``KMPArray[i] = j;``                ``i++;``            ``}``        ``}``    ``}``}` `// Function to print the maximum``// possible length``static` `void` `printAnswer(``int``[] a, ``int``[] sequence)``{``    ` `    ``// Length of the given sequence``    ``m = sequence.Length;` `    ``// Initialize kmp array``    ``KMPArray = ``new` `int``[m];` `    ``// Generate KMP array``    ``fillKMPArray(sequence);` `    ``// Initialize dp``    ``dp = ``new` `int``[a.Length, a.Length, a.Length];` `    ``// Initialize the states to -1``    ``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;` `    ``// Get answer``    ``int` `ans = findSubsequence(a, sequence, 0, -1, 0);` `    ``// Print answer``    ``Console.WriteLine((ans < 0) ? 0 : ans);``}` `// Driver code``public` `static` `void` `Main()``{``    ` `    ``// Given array``    ``int``[] arr = { 5, 3, 9, 3, 4, 7 };` `    ``// Give arr1``    ``int``[] arr1 = { 3, 4 };` `    ``// Function Call``    ``printAnswer(arr, arr1);``}``}` `// This code is contributed by akhilsaini`
Output:
`3`

Time Complexity: O(N3)
Auxiliary Space: O(N3)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

My Personal Notes arrow_drop_up