# Maximum length subsequence such that adjacent elements in the subsequence have a common factor

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[] = { 1, 2, 2, 3, 3, 1 }
Output: 2

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++ implementation of the above approach ` `#include ` `#define N 100005 ` `#define MAX 10000002 ` ` `  `using` `namespace` `std; ` ` `  `int` `lpd[MAX]; ` ` `  `// 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 = 1; i <= n; i++) ` `        ``dp[i] = 1; ` ` `  `    ``for` `(``int` `i = 1; 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 = 1; 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 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``(``1``, 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``(``1``, 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 implementation of the above approach  ` `import` `java.util.*; ` `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[``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(``int` `arr[], ``int` `n)  ` `{  ` `    ``int` `dp[] = ``new` `int``[N];  ` `Map pos = ``new` `HashMap ();  ` ` `  `    ``// Initialize dp array with 1.  ` `    ``for` `(``int` `i = ``1``; i <= n; i++)  ` `        ``dp[i] = ``1``;  ` ` `  `    ``for` `(``int` `i = ``1``; 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 = ``1``;  ` `    ``for` `(``int` `i = ``1``; i <= n; i++) ` `    ``{  ` `        ``ans = Math.max(ans, dp[i]);  ` `    ``}  ` ` `  `    ``return` `ans;  ` `}  ` ` `  `// Driver code  ` `public` `static` `void` `main(String[] args)  ` `{  ` `    ``int` `arr[] = { ``13``, ``2``, ``8``, ``6``, ``3``, ``1``, ``9` `};  ` `    ``int` `n = arr.length - ``1``;  ` ` `  `    ``preCompute();  ` `    ``System.out.println(maxLengthSubsequence(arr, n));  ` `} ` `}  ` ` `  `// This code is contributed by Prerna Saini. `

 `// 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 = 1; i <= n; i++)  ` `        ``dp[i] = 1;  ` ` `  `    ``for` `(``int` `i = 1; 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 = 1; 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
```

An enthusiastic Java and web developer with a little affinity for tea, cricket, English, etymology, and reading

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.

Article Tags :