Longest Ideal Subsequence

Updated on 03 June, 2025
Longest Ideal Subsequence header image

Problem Statement

You are provided with a string s composed solely of lowercase English letters, accompanied by an integer k. A subsequence t derived from s is deemed ideal if it meets the following criteria:

  • t is a subsequence of s, which means it can be obtained by deleting some or none of the characters from s without rearranging the order of the remaining characters.
  • For every two consecutive letters in t, the absolute difference in their alphabetical order is less than or equal to k.

The challenge is to determine and return the length of the longest such ideal string t. It’s important to remember that in this context, the difference in alphabetical positions of letters is direct (not cyclic), so the difference between 'a' and 'z' is 25.

Examples

Example 1

Input:

s = "acfgbd", k = 2

Output:

4

Explanation:

The longest ideal string is "acbd". The length of this string is 4, so 4 is returned.
Note that "acfgbd" is not ideal because 'c' and 'f' have a difference of 3 in alphabet order.

Example 2

Input:

s = "abcd", k = 3

Output:

4

Explanation:

The longest ideal string is "abcd". The length of this string is 4, so 4 is returned.

Constraints

  • 1 <= s.length <= 105
  • 0 <= k <= 25
  • s consists of lowercase English letters.

Approach and Intuition

The problem can be approached using dynamic programming, which allows us to build up a solution by breaking it down into smaller subproblems and using the results of these subproblems to construct the solution to the larger problem. Given the constraints, especially the potentially large size of string s and variable k, an efficient solution is crucial. Here’s a step-by-step approach based on examples provided:

  1. Understanding the Constraints and Setup: The absolute difference for every adjacent letters in the ideal string should not exceed k. This means that for any character x in s, the next character y in the ideal string t must satisfy |x-y| <= k.

  2. Initiate a Dynamic Programming Array: One way to tackle this problem is to use a dynamic programming array where dp[i] represents the longest ideal subsequence possible ending with the letter that has an ASCII value of i.

  3. Iterate Over the Given String: For each character in string s, update the dp array based on possible transitions from characters x such that the difference |current character - x| <= k.

  4. Translating the Conditions Into Logic: For each character in s, look for all possible characters x (within the allowable alphabet difference k) that could precede it in the ideal string. Update the maximum length found for sequences ending with this character.

  5. Using Examples for Validation:

    • For s = "abcd", k = 3: The sequence "abcd" itself is ideal since all consecutive letters are within 3 places of each other. Therefore, the result for this input is rightly 4.
    • For s = "acfgbd", k = 2: The sequence "acbd" demonstrates the method well – each pair of adjacent characters ('a' to 'c', 'c' to 'b', 'b' to 'd') obeys the k limit. Hence, sequence "acfgbd" isn’t ideal because the pair ('c', 'f') exceeds the limit, affirming 4 as the correct answer.
  6. Final Step: The overall solution is the maximum value found in the dp array after processing all characters of s.

Applying this approach ensures an efficient check on all subsequences visually and programmatically, ensuring no possibilities are missed, while also maintaining optimal performance within provided constraints.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    int maxIdealSubstrLen(string text, int maxDiff) {
        int len = text.length();
        vector<int> counts(26, 0);

        int maxLen = 0;
        for (int idx = 0; idx < len; idx++) {
            int charIdx = text[idx] - 'a';
            int localMax = 0;
            for (int j = max(0, charIdx - maxDiff); j < min(26, charIdx + maxDiff + 1); j++) {
                localMax = max(localMax, counts[j]);
            }

            counts[charIdx] = localMax + 1;
            maxLen = max(maxLen, counts[charIdx]);
        }

        return maxLen;
    }
};

The provided C++ code defines a method to find the length of the longest ideal subsequence in a given string where the subsequence only contains characters that are within a specified maximum difference in their alphabetical order.

Here’s an explanation of how the code works:

  • The maxIdealSubstrLen function accepts a string text and an integer maxDiff:

    • text: The input string from which the subsequence needs to be found.
    • maxDiff: The maximum difference allowed between the indices of two characters in the sequence.
  • The solution uses dynamic programming. An array counts of size 26 (corresponding to the letters of the alphabet) is initialized to zero. This array tracks the maximum length of an ideal subsequence that ends with each corresponding letter of the alphabet.

  • Iterate over each character in the string. For each character at index idx in text:

    • Calculate charIdx which is the numeric position of the character in the alphabet (0 for 'a', 1 for 'b', etc.).

    • Determine the range of characters that can follow the current character in an ideal subsequence based on maxDiff:

      • Start of the range is greater of 0 or (charIdx - maxDiff).
      • End of the range is smaller of 25 or (charIdx + maxDiff).
    • For each character index j within the allowed range, update the local maximum length of an ideal subsequence considering the sequence ending at character j.

    • Update the counts[charIdx] to the best found local maximum length plus one (for the current character).

    • Continuously update maxLen, the variable tracking the overall maximum length of any ideal subsequence found.

  • Finally, return maxLen, which holds the length of the longest ideal subsequence that adheres to the given conditions.

With this implementation, one efficiently determines the longest subsequence length where the character distances comply with the maxDiff constraint. The approach optimally processes each character in the string once, making the computation reasonably efficient for strings with significant lengths.

java
class Solution {
    public int maxIdealSubsequenceLength(String inputString, int maxDiff) {
        int stringLength = inputString.length();
        int[] maxLength = new int[26];
        int maximumResult = 0;

        for (int i = 0; i < stringLength; i++) {
            int charIndex = inputString.charAt(i) - 'a';
            int currentMax = 0;

            for (int j = Math.max(0, charIndex - maxDiff); j < Math.min(26, charIndex + maxDiff + 1); j++) {
                currentMax = Math.max(currentMax, maxLength[j]);
            }

            maxLength[charIndex] = currentMax + 1;
            maximumResult = Math.max(maximumResult, maxLength[charIndex]);
        }
        
        return maximumResult;
    }
}

This solution pertains to the "Longest Ideal Subsequence" problem and is implemented in Java. The focus is on calculating the maximum length of a subsequence from a given string such that the absolute difference between the characters, in terms of their positions in the alphabet, does not exceed a specified value maxDiff.

To achieve the solution:

  1. Initialize the length of the input string for processing.
  2. Create an array maxLength of size 26 (corresponding to the letters of the alphabet) to store the maximum subsequence length achievable for each character end point.
  3. Set up a variable maximumResult to store the overall maximum subsequence length found during the solution process.

For each character in the string:

  1. Determine its index in the alphabet (0 for 'a', 25 for 'z') and store it in charIndex.
  2. Calculate the potential range of character indices that can follow the current character allowed by the maxDiff constraint.
  3. Traverse these indices to find the current maximum achievable subsequence length and update it for the current character by adding 1 (to count the current character itself).
  4. Update the overall maximum subsequence length (maximumResult) if the current character leads to a longer subsequence than previously recorded.

Finally, the function returns the maximumResult, which is the length of the longest ideal subsequence under the given constraints. This approach uses dynamic programming by leveraging previously computed results stored in the maxLength array to optimize the solution process.

python
class IdealStringCalculator:
    def computeLongestIdeal(self, sequence: str, allowed_diff: int) -> int:
        sequence_length = len(sequence)
        dp_lengths = [0] * 26  # Dynamic programming list for maximum lengths per character

        maximum_length = 0
        for char_index in range(sequence_length):
            cur_char_position = ord(sequence[char_index]) - ord('a')
            longest_for_char = 0
            for prev_char_position in range(max(0, cur_char_position - allowed_diff), min(26, cur_char_position + allowed_diff + 1)):
                longest_for_char = max(longest_for_char, dp_lengths[prev_char_position])

            dp_lengths[cur_char_position] = longest_for_char + 1
            maximum_length = max(maximum_length, dp_lengths[cur_char_position])

        return maximum_length

This solution is for the problem of finding the longest ideal subsequence in a given string where the difference between the alphabet indices of any two consecutive characters in the subsequence doesn't exceed a specified limit.

  • The solution is provided in Python and implemented in a class called IdealStringCalculator.
  • The computeLongestIdeal function takes two parameters:
    • sequence: the input string to analyze.
    • allowed_diff: an integer representing the maximum allowed difference between the indices of any two consecutive characters in the subsequence.

Here's how the solution works:

  1. The length of the input string sequence is stored in sequence_length.
  2. A list dp_lengths of size 26 (for each letter of the English alphabet) is initialized to zero. This list is used for dynamic programming to store the maximum length of the ideal subsequence ending with each letter.
  3. A variable maximum_length is initialized to zero to keep track of the maximum length found so far.
  4. The function loops through each character in the input sequence. In each iteration, the position of the current character in the alphabet (cur_char_position) is calculated using ASCII values.
  5. For each character, the function checks possible previous characters within the allowed difference range. It updates longest_for_char to store the maximum length of any ideal subsequence that could end with this character.
  6. The dynamic programming list dp_lengths is updated for the current character position to be the maximum of the previously computed value and longest_for_char + 1.
  7. maximum_length is updated to reflect the longest ideal subsequence found so far if the current character results in a longer subsequence.
  8. Finally, maximum_length is returned, which represents the length of the longest ideal subsequence found.

This dynamic programming approach ensures that all possible ideal subsequences are considered efficiently, leading to a solution that is both comprehensive and optimal for the problem constraints.

Comments

No comments yet.