Related Articles
Maximum length subsequence such that adjacent elements in the subsequence have a common factor
• Difficulty Level : Hard
• Last Updated : 05 Nov, 2020

Given an array arr[], the task is to find the maximum length of a subsequence such that the adjacent elements in the subsequence have a common factor.

Examples:

Input: arr[] = { 13, 2, 8, 6, 3, 1, 9 }
Output: 5
Max length subsequence with satisfied conditions: { 2, 8, 6, 3, 9 }

Input: arr[] = { 12, 2, 8, 6, 3, 1, 9 }
Output: 6
Max length subsequence with satisfied conditions: {12, 2, 8, 6, 3, 9 }

Input: arr[] = { 1, 2, 2, 3, 3, 1 }
Output:

Approach: A naive approach is to consider all subsequences and check every subsequence whether it satisfies the condition.
An efficient solution is to use Dynamic programming. Let dp[i] denote the maximum length of subsequence including arr[i]. Then, the following relation holds for every prime p such that p is a prime factor of arr[i]:

```dp[i] = max(dp[i], 1 + dp[pos[p]])
where pos[p] gives the index of p in the array
where it last occurred.
```

Explanation: Traverse the array. For an element arr[i], there are 2 possibilities.

1. If the prime factors of arr[i] have shown their first appearance in the array, then dp[i] = 1
2. If the prime factors of arr[i] have already occurred, then this element can be added in the subsequence since there’s a common factor. Hence dp[i] = max(dp[i], 1 + dp[pos[p]]) where p is the common prime factor and pos[p] is the latest index of p in the array.

Below is the implementation of the above approach:

## C++

 `// C++ implementation of the above approach``#include ``#define N 100005``#define MAX 10000002` `using` `namespace` `std;` `int` `lpd[MAX];` `// Function to compute least``// prime divisor of i``void` `preCompute()``{``    ``memset``(lpd, 0, ``sizeof``(lpd));``    ``lpd = lpd = 1;``    ``for` `(``int` `i = 2; i * i < MAX; i++)``    ``{``        ``for` `(``int` `j = i * 2; j < MAX; j += i)``        ``{``            ``if` `(lpd[j] == 0)``            ``{``                ``lpd[j] = i;``            ``}``        ``}``    ``}``    ``for` `(``int` `i = 2; i < MAX; i++)``    ``{``        ``if` `(lpd[i] == 0)``        ``{``            ``lpd[i] = i;``        ``}``    ``}``}` `// Function that returns the maximum``// length subsequence such that``// adjacent elements have a common factor.``int` `maxLengthSubsequence(``int` `arr[], ``int` `n)``{``    ``int` `dp[N];``    ``unordered_map<``int``, ``int``> pos;` `    ``// Initialize dp array with 1.``    ``for` `(``int` `i = 0; i <= n; i++)``        ``dp[i] = 1;` `    ``for` `(``int` `i = 0; i <= n; i++)``    ``{``        ``while` `(arr[i] > 1)``        ``{``            ``int` `p = lpd[arr[i]];``            ``if` `(pos[p])``            ``{``                ``// p has appeared at least once.``                ``dp[i] = max(dp[i], 1 + dp[pos[p]]);``            ``}` `            ``// Update latest occurrence of prime p.``            ``pos[p] = i;``            ``while` `(arr[i] % p == 0)``                ``arr[i] /= p;``        ``}``    ``}` `    ``// Take maximum value as the answer.``    ``int` `ans = 1;``    ``for` `(``int` `i = 0; i <= n; i++)``    ``{``        ``ans = max(ans, dp[i]);``    ``}` `    ``return` `ans;``}` `// Driver code``int` `main()``{``    ``int` `arr[] = { 13, 2, 8, 6, 3, 1, 9 };``    ``int` `n = ``sizeof``(arr) / ``sizeof``(arr);` `    ``preCompute();` `    ``cout << maxLengthSubsequence(arr, n);``    ``return` `0;``}`

## Python3

 `# Python3 implementation of the``# above approach``import` `math as mt` `N ``=` `100005``MAX` `=` `1000002` `lpd ``=` `[``0` `for` `i ``in` `range``(``MAX``)]` `# to compute least prime divisor of i`  `def` `preCompute():` `    ``lpd[``0``], lpd[``1``] ``=` `1``, ``1` `    ``for` `i ``in` `range``(``2``, mt.ceil(mt.sqrt(``MAX``))):``        ``for` `j ``in` `range``(``2` `*` `i, ``MAX``, i):``            ``if` `(lpd[j] ``=``=` `0``):``                ``lpd[j] ``=` `i` `    ``for` `i ``in` `range``(``2``, ``MAX``):``        ``if` `(lpd[i] ``=``=` `0``):``            ``lpd[i] ``=` `i` `# Function that returns the maximum``# length subsequence such that``# adjacent elements have a common factor.`  `def` `maxLengthSubsequence(arr, n):``    ``dp ``=` `[``1` `for` `i ``in` `range``(N ``+` `1``)]` `    ``pos ``=` `dict``()` `    ``# Initialize dp array with 1.``    ``for` `i ``in` `range``(``0``, n):``        ``while` `(arr[i] > ``1``):``            ``p ``=` `lpd[arr[i]]``            ``if` `(p ``in` `pos.keys()):` `                ``# p has appeared at least once.``                ``dp[i] ``=` `max``(dp[i], ``1` `+` `dp[pos[p]])` `            ``# Update latest occurrence of prime p.``            ``pos[p] ``=` `i``            ``while` `(arr[i] ``%` `p ``=``=` `0``):``                ``arr[i] ``/``/``=` `p` `    ``# Take maximum value as the answer.``    ``ans ``=` `1``    ``for` `i ``in` `range``(``0``, n ``+` `1``):``        ``ans ``=` `max``(ans, dp[i])` `    ``return` `ans`  `# Driver code``arr ``=` `[``13``, ``2``, ``8``, ``6``, ``3``, ``1``, ``9``]``n ``=` `len``(arr)` `preCompute()` `print``(maxLengthSubsequence(arr, n))` `# This code is contributed by Mohit Kumar`

## Java

 `// Java implementation of the above approach``import` `java.util.*;``class` `GfG {``    ``static` `int` `N, MAX;` `    ``// Check if UpperBound is``    ``// given for all test Cases``    ``// N = 100005 ;``    ``// MAX = 10000002;``    ``static` `int` `lpd[];` `    ``// Function to compute least prime divisor``    ``// of i upto MAX element of the  input array``    ``// it will be space efficient``    ``// if more test cases are there it's``    ``// better to find prime divisor``    ``// upto upperbound of input element``    ``// it will be cost efficient``    ``static` `void` `preCompute()``    ``{``        ``lpd = ``new` `int``[MAX + ``1``];``        ``lpd[``0``] = lpd[``1``] = ``1``;``        ``for` `(``int` `i = ``2``; i * i <= MAX; i++)``        ``{``            ``for` `(``int` `j = i * ``2``; j <= MAX; j += i)``            ``{``                ``if` `(lpd[j] == ``0``)``                ``{``                    ``lpd[j] = i;``                ``}``            ``}``        ``}``        ``for` `(``int` `i = ``2``; i <= MAX; i++)``        ``{``            ``if` `(lpd[i] == ``0``)``            ``{``                ``lpd[i] = i;``            ``}``        ``}``    ``}` `    ``// Function that returns the maximum``    ``// length subsequence such that``    ``// adjacent elements have a common factor.``    ``static` `int` `maxLengthSubsequence(Integer arr[], ``int` `n)``    ``{``        ``Integer dp[] = ``new` `Integer[N];``        ``Map pos``            ``= ``new` `HashMap();` `        ``// Initialize dp array with 1.``        ``for` `(``int` `i = ``0``; i <= n; i++)``            ``dp[i] = ``1``;` `        ``for` `(``int` `i = ``0``; i <= n; i++)``        ``{``            ``while` `(arr[i] > ``1``) {``                ``int` `p = lpd[arr[i]];``                ``if` `(pos.containsKey(p))``                ``{``                    ``// p has appeared at least once.``                    ``dp[i] = Math.max(dp[i],``                                     ``1` `+ dp[pos.get(p)]);``                ``}` `                ``// Update latest occurrence of prime p.``                ``pos.put(p, i);``                ``while` `(arr[i] % p == ``0``)``                    ``arr[i] /= p;``            ``}``        ``}` `        ``// Take maximum value as the answer.``        ``int` `ans = Collections.max(Arrays.asList(dp));``        ``return` `ans;``    ``}` `    ``// Driver code``    ``public` `static` `void` `main(String[] args)``    ``{``        ``Integer arr[] = { ``12``, ``2``, ``8``, ``6``, ``3``, ``1``, ``9` `};``        ``N = arr.length;``        ``MAX = Collections.max(Arrays.asList(arr));``        ``preCompute();``        ``System.out.println(``            ``maxLengthSubsequence(arr, N - ``1``));``    ``}``}` `// This code is contributed by Prerna Saini.`

## C#

 `// C# implementation of the``// above approach``using` `System;``using` `System.Collections;` `class` `GFG {` `    ``static` `int` `N = 100005;``    ``static` `int` `MAX = 10000002;` `    ``static` `int``[] lpd = ``new` `int``[MAX];` `    ``// to compute least prime divisor of i``    ``static` `void` `preCompute()``    ``{``        ``lpd = lpd = 1;``        ``for` `(``int` `i = 2; i * i < MAX; i++)``        ``{``            ``for` `(``int` `j = i * 2; j < MAX; j += i)``            ``{``                ``if` `(lpd[j] == 0)``                ``{``                    ``lpd[j] = i;``                ``}``            ``}``        ``}``        ``for` `(``int` `i = 2; i < MAX; i++)``        ``{``            ``if` `(lpd[i] == 0)``            ``{``                ``lpd[i] = i;``            ``}``        ``}``    ``}` `    ``// Function that returns the maximum``    ``// length subsequence such that``    ``// adjacent elements have a common factor.``    ``static` `int` `maxLengthSubsequence(``int``[] arr, ``int` `n)``    ``{``        ``int``[] dp = ``new` `int``[N];``        ``Hashtable pos = ``new` `Hashtable();` `        ``// Initialize dp array with 1.``        ``for` `(``int` `i = 0; i <= n; i++)``            ``dp[i] = 1;` `        ``for` `(``int` `i = 0; i <= n; i++)``        ``{``            ``while` `(arr[i] > 1) {``                ``int` `p = lpd[arr[i]];``                ``if` `(pos.ContainsKey(p))``                ``{``                    ``// p has appeared at least once.``                    ``dp[i] = Math.Max(``                        ``dp[i],``                        ``1 + dp[Convert.ToInt32(pos[p])]);``                ``}` `                ``// Update latest occurrence of prime p.``                ``pos[p] = i;``                ``while` `(arr[i] % p == 0)``                    ``arr[i] /= p;``            ``}``        ``}` `        ``// Take maximum value as the answer.``        ``int` `ans = 1;``        ``for` `(``int` `i = 0; i <= n; i++)``        ``{``            ``ans = Math.Max(ans, dp[i]);``        ``}` `        ``return` `ans;``    ``}` `    ``// Driver code``    ``public` `static` `void` `Main()``    ``{``        ``int``[] arr = { 13, 2, 8, 6, 3, 1, 9 };``        ``int` `n = arr.Length - 1;` `        ``preCompute();``        ``Console.WriteLine(maxLengthSubsequence(arr, n));``    ``}``}` `// This code is contributed by Ryuga`
Output
`5`

Time Complexity: O(N* log(N))
Auxiliary Space: O(N)

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.  Get hold of all the important mathematical concepts for competitive programming with the Essential Maths for CP Course at a student-friendly price.

In case you wish to attend live classes with industry experts, please refer Geeks Classes Live and Geeks Classes Live USA

My Personal Notes arrow_drop_up