Open In App

Longest subsequence having difference atmost K

Given a string S of length N and an integer K, the task is to find the length of longest sub-sequence such that the difference between the ASCII values of adjacent characters in the subsequence is not more than K.

Examples: 

Input: N = 7, K = 2, S = "afcbedg"
Output: 4
Explanation:
Longest special sequence present 
in "afcbedg" is a, c, b, d.
It is special because |a - c| <= 2, 
|c - b| <= 2 and | b-d| <= 2

Input: N = 13, K = 3, S = "geeksforgeeks"
Output: 7

Naive approach: A brute force solution is to generate all the possible subsequences of various lengths and compute the maximum length of the valid subsequence. The time complexity will be exponential.

Efficient Approach: An efficient approach is to use the concept Dynamic Programming 

input string s is “afcbedg” and k is 2 
 

  • for 1st iteration value of i is ‘a’ and range of j is (0, 2) 
    and current dp = [1, 0, 0, 0, 0, 0, 0]
  • for 2nd iteration value of i is ‘f’ and range of j is (3, 7) 
    and current dp = [1, 1, 0, 0, 0, 0, 0]
  • for 3rd iteration value of i is ‘c’ and range of j is (0, 4) 
    and current dp = [1, 1, 2, 0, 0, 0, 0]
  • for 4th iteration value of i is ‘b’ and range of j is (0, 3) 
    and current dp = [1, 1, 2, 3, 0, 0, 0]
  • for 5th iteration value of i is ‘e’ and range of j is (2, 6) 
    and current dp = [1, 1, 2, 3, 3, 0, 0]
  • for 6th iteration value of i is ‘d’ and range of j is (1, 5) 
    and current dp = [1, 1, 2, 3, 3, 4, 0]
  • for 7th iteration value of i is ‘g’ and range of j is (4, 8) 
    and current dp = [1, 1, 2, 3, 3, 4, 4]

longest length is the maximum value in dp so maximum length is 4 
 

Below is the implementation of the above approach:  




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to find
// the longest Special Sequence
int longest_subseq(int n, int k, string s)
{
 
    // Creating a list with
    // all 0's of size
    // equal to the length of string
    vector<int> dp(n, 0);
 
    // Supporting list with
    // all 0's of size 26 since
    // the given string consists
    // of only lower case alphabets
    int max_length[26] = {0};
 
    for (int i = 0; i < n; i++)
    {
 
        // Converting the ascii value to
        // list indices
        int curr = s[i] - 'a';
         
        // Determining the lower bound
        int lower = max(0, curr - k);
         
        // Determining the upper bound
        int upper = min(25, curr + k);
         
        // Filling the dp array with values
        for (int j = lower; j < upper + 1; j++)
        {
            dp[i] = max(dp[i], max_length[j] + 1);
        }
        //Filling the max_length array with max
        //length of subsequence till now
        max_length[curr] = max(dp[i], max_length[curr]);
    }
 
    int ans = 0;
 
    for(int i:dp) ans = max(i, ans);
 
    // return the max length of subsequence
    return ans;
}
 
// Driver Code
int main()
{
    string s = "geeksforgeeks";
    int n = s.size();
    int k = 3;
    cout << (longest_subseq(n, k, s));
    return 0;
}
 
// This code is contributed by Mohit Kumar




// Java program for the above approach
class GFG
{
 
// Function to find
// the longest Special Sequence
static int longest_subseq(int n, int k, String s)
{
 
    // Creating a list with
    // all 0's of size
    // equal to the length of String
    int []dp = new int[n];
 
    // Supporting list with
    // all 0's of size 26 since
    // the given String consists
    // of only lower case alphabets
    int []max_length = new int[26];
 
    for (int i = 0; i < n; i++)
    {
 
        // Converting the ascii value to
        // list indices
        int curr = s.charAt(i) - 'a';
         
        // Determining the lower bound
        int lower = Math.max(0, curr - k);
         
        // Determining the upper bound
        int upper = Math.min(25, curr + k);
         
        // Filling the dp array with values
        for (int j = lower; j < upper + 1; j++)
        {
            dp[i] = Math.max(dp[i], max_length[j] + 1);
        }
         
        // Filling the max_length array with max
        // length of subsequence till now
        max_length[curr] = Math.max(dp[i], max_length[curr]);
    }
 
    int ans = 0;
 
    for(int i:dp) ans = Math.max(i, ans);
 
    // return the max length of subsequence
    return ans;
}
 
// Driver Code
public static void main(String[] args)
{
    String s = "geeksforgeeks";
    int n = s.length();
    int k = 3;
    System.out.print(longest_subseq(n, k, s));
}
}
 
// This code is contributed by 29AjayKumar




# Function to find
# the longest Special Sequence
def longest_subseq(n, k, s):
   
    # Creating a list with
    # all 0's of size
    # equal to the length of string
    dp = [0] * n
     
    # Supporting list with
    # all 0's of size 26 since
    # the given string consists
    # of only lower case alphabets
    max_length = [0] * 26
 
    for i in range(n):
 
        # Converting the ascii value to
        # list indices
        curr = ord(s[i]) - ord('a')
        # Determining the lower bound
        lower = max(0, curr - k)
        # Determining the upper bound
        upper = min(25, curr + k)
        # Filling the dp array with values
        for j in range(lower, upper + 1):
 
            dp[i] = max(dp[i], max_length[j]+1)
        # Filling the max_length array with max
        # length of subsequence till now
        max_length[curr] = max(dp[i], max_length[curr])
 
    # return the max length of subsequence
    return max(dp)
 
# driver code
def main():
  s = "geeksforgeeks"
  n = len(s)
  k = 3
  print(longest_subseq(n, k, s))
 
main()




// C# program for the above approach
using System;
 
class GFG
{
 
// Function to find
// the longest Special Sequence
static int longest_subseq(int n, int k, String s)
{
 
    // Creating a list with
    // all 0's of size
    // equal to the length of String
    int []dp = new int[n];
 
    // Supporting list with
    // all 0's of size 26 since
    // the given String consists
    // of only lower case alphabets
    int []max_length = new int[26];
 
    for (int i = 0; i < n; i++)
    {
 
        // Converting the ascii value to
        // list indices
        int curr = s[i] - 'a';
         
        // Determining the lower bound
        int lower = Math.Max(0, curr - k);
         
        // Determining the upper bound
        int upper = Math.Min(25, curr + k);
         
        // Filling the dp array with values
        for (int j = lower; j < upper + 1; j++)
        {
            dp[i] = Math.Max(dp[i], max_length[j] + 1);
        }
         
        // Filling the max_length array with max
        // length of subsequence till now
        max_length[curr] = Math.Max(dp[i], max_length[curr]);
    }
 
    int ans = 0;
 
    foreach(int i in dp) ans = Math.Max(i, ans);
 
    // return the max length of subsequence
    return ans;
}
 
// Driver Code
public static void Main(String[] args)
{
    String s = "geeksforgeeks";
    int n = s.Length;
    int k = 3;
    Console.Write(longest_subseq(n, k, s));
}
}
 
// This code is contributed by Rajput-Ji




<script>
// Javascript program for the above approach
 
// Function to find
// the longest Special Sequence
function longest_subseq(n, k, s)
{
 
    // Creating a list with
    // all 0's of size
    // equal to the length of String
    let dp = new Array(n);
   
    // Supporting list with
    // all 0's of size 26 since
    // the given String consists
    // of only lower case alphabets
    let max_length = new Array(26);
       
    for(let i = 0; i < 26; i++)
    {
        max_length[i] = 0;
        dp[i] = 0;
    }
    for (let i = 0; i < n; i++)
    {
   
        // Converting the ascii value to
        // list indices
        let curr = s[i].charCodeAt(0) - 'a'.charCodeAt(0);
           
        // Determining the lower bound
        let lower = Math.max(0, curr - k);
           
        // Determining the upper bound
        let upper = Math.min(25, curr + k);
           
        // Filling the dp array with values
        for (let j = lower; j < upper + 1; j++)
        {
            dp[i] = Math.max(dp[i], max_length[j] + 1);
        }
           
        // Filling the max_length array with max
        // length of subsequence till now
        max_length[curr] = Math.max(dp[i], max_length[curr]);
    }
   
    let ans = 0;
    ans = Math.max(...dp)
   
    // return the max length of subsequence
    return ans;
}
 
// Driver Code
let s = "geeksforgeeks";
let n = s.length;
let k = 3;
document.write(longest_subseq(n, k, s));
 
// This code is contributed by unknown2108
</script>

Output: 
7

 

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


Article Tags :