Facebook Pixel

3628. Maximum Number of Subsequences After One Inserting

Problem Description

You are given a string s consisting of uppercase English letters.

You are allowed to insert at most one uppercase English letter at any position (including the beginning or end) of the string.

Return the maximum number of "LCT" subsequences that can be formed in the resulting string after at most one insertion.

A subsequence is a sequence that can be derived from the string by deleting some or no letters without changing the order of the remaining letters.

For example, if s = "LCT" and you insert a 'T' at the end to get "LCTT", subsequences like "LCT" and "LCT" (using the second 'T') are both counted.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

To maximize the number of "LCT" subsequences after at most one insertion, first think about how such subsequences form: for every 'C' in the string, you can pair any 'L' before it with any 'T' after it. So, for each 'C', the number of new subsequences is the product of the count of 'L' before and 'T' after. The total is the sum over all 'C'.

Now, with the option of one insertion, the best way to increase the count is to insert 'L', 'C', or 'T' to create more combinations:

  • Inserting 'L' increases the number of possible "LCT" by boosting all "CT" subsequences.
  • Inserting 'C' increases the count by helping form "LCT" from every combination of 'L' before and 'T' after where the new letter is the center 'C'.
  • Inserting 'T' connects all "LC" pairs into new "LCT" subsequences.

The task then is to try these three insert options separately and, in each case, count how many new "LCT" subsequences are created, then pick the maximum result overall. This way, we consider all possible single insertions to ensure the answer is maximized.

Solution Approach

To solve this problem efficiently, we need to count the number of "LCT" subsequences before and after one possible insertion.

The key is to recognize that for each 'C' in the string, the number of "LCT" subsequences that use that 'C' is the product of the number of 'L' characters to its left and the number of 'T' characters to its right. So, for each character, we keep two running totals:

  • l: the number of 'L's encountered so far (to the left)
  • r: the number of 'T's remaining to the right

The main algorithm is:

  1. Count the total number of 'T's in the string and store it in r.
  2. Traverse the string from left to right:
    • For every character, if it's a 'C', calculate how many 'L's have appeared before (l) and how many 'T's remain after (r), then add l * r to the answer.
    • If the character is 'L', increase l by 1.
    • If the character is 'T', decrease r by 1 since one 'T' is now to the left.
    • Keep track of the maximum possible l * r, which represents the result after inserting a 'C' at the best spot.

Next, consider all three possible types of insertions:

  • Insert an 'L': This helps create new "LCT" from each "CT" pair. So, compute the total number of "CT" subsequences. We can do this by scanning the string for every 'T' and counting the number of 'C's before it, accumulating that count.
  • Insert a 'C': For this, maximize the product l * r where we pick some potential place to insert 'C'.
  • Insert a 'T': We compute the total number of "LC" subsequences. This requires traversing the string and, for each 'C' found, adding the current count of 'L'.

The code calculates the result of each of these choices and returns the initial number of "LCT" plus the largest possible increase achievable by one insertion.

All calculations are done in linear time, making the approach efficient even for longer strings, since each step is an O(n) traversal or operation.

Ready to land your dream job?

Unlock your dream job with a 2-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's use the string s = "LCTC" as an example.

Step 1: Calculate Initial "LCT" Subsequences

We want to count all the "LCT" subsequences in s. For each 'C', count all 'L' to its left and all 'T' to its right.

  • First 'C' at index 1: 'L' to the left: 1 (s[0]) 'T' to the right: 1 (s[2]) Total for this 'C': (1 \times 1 = 1)

  • Second 'C' at index 3: 'L' to the left: 1 (s[0]) 'T' to the right: 0 Total for this 'C': (1 \times 0 = 0)

So, initially there is 1 "LCT" subsequence.

Step 2: Evaluate Inserting Each Possible Character

A) Insert 'L'

After inserting an extra 'L', count the number of "CT" pairs.

  • Scan from left to right:
    • For each 'T', count how many 'C's were before it.
  • 'C' before 'T' (s[2]): 1 (s[1]) So, one "CT" pair exists. Adding an 'L' creates an extra "LCT" for each "CT" pair: +1

B) Insert 'C'

Find the maximum value of (number of L's before (\times) number of T's after) at any position (including beginning/end or between). Track cumulative 'L's from left and 'T's from right.

Record at each position:

  • Before index 0: L=0, T=2 → (0 \times 2 = 0)
  • Between 0-1: L=1, T=2 → (1 \times 2 = 2)
  • Between 1-2: L=1, T=1 → (1 \times 1 = 1)
  • Between 2-3: L=1, T=1 → (1 \times 1 = 1)
  • After index 3: L=1, T=0 → (1 \times 0 = 0)

The max is 2, so by inserting 'C' between the first 'L' and the first 'C', we gain +2 new "LCT" subsequences.

C) Insert 'T'

Count the number of "LC" pairs.

  • Scan from left to right: For each 'C', add the current count of 'L's before it.
  • First 'C' (s[1]): L=1 → +1
  • Second 'C' (s[3]): L=1 → +1

Total "LC" pairs: 2. Adding a 'T' gives an extra "LCT" for each "LC" pair: +2

Step 3: Get the Maximum

  • Original "LCT" subsequences: 1
  • Insert 'L': 1 + 1 = 2
  • Insert 'C': 1 + 2 = 3
  • Insert 'T': 1 + 2 = 3

Maximum achievable subsequences: 3

Summary

For s = "LCTC", after at most one optimal character insertion, the maximum number of "LCT" subsequences is 3.

Solution Implementation

1class Solution:
2    def numOfSubsequences(self, s: str) -> int:
3        # Helper function to count subsequences of the form t[0]...t[1] (e.g. 'LC' or 'CT')
4        def calc(t: str) -> int:
5            subseq_count = 0     # Number of valid subsequences
6            count_first = 0      # Count of t[0] seen so far
7            for char in s:
8                if char == t[1]:
9                    subseq_count += count_first
10                if char == t[0]:
11                    count_first += 1
12            return subseq_count
13
14        left_L = 0                  # Number of 'L' seen so far
15        right_T = s.count("T")      # Number of 'T' remaining to the right
16        answer = 0                  # Final answer (sum of all wanted subsequences)
17        max_value = 0               # Maximum value for special cases
18
19        # Iterate through the string once to count 'L...C...T' type subsequences
20        for char in s:
21            right_T -= int(char == "T")     # Decrease T count as we move past
22            if char == "C":
23                answer += left_L * right_T  # For each 'C', add possible (L on left) * (T on right)
24            if char == "L":
25                left_L += 1
26            max_value = max(max_value, left_L * right_T)   # Track max possible product
27
28        # Consider the best two-letter subsequences and single max_value
29        max_value = max(max_value, calc("LC"), calc("CT"))
30        answer += max_value
31
32        return answer
33
1class Solution {
2    private char[] s; // Character array to store the string
3
4    // Main method to count the number of specific subsequences
5    public long numOfSubsequences(String S) {
6        s = S.toCharArray();
7
8        int countL = 0; // Counts number of 'L's seen so far (to the left)
9        int countT = 0; // Counts number of 'T's remaining (to the right, including current)
10        for (char c : s) {
11            if (c == 'T') {
12                ++countT;
13            }
14        }
15
16        long total = 0;   // Final answer
17        long maxVal = 0;  // Maximum l * r seen for 'C' position
18
19        // Traverse the string to calculate the number of valid subsequences
20        for (char c : s) {
21            if (c == 'T') {
22                countT--;
23            }
24            if (c == 'C') {
25                // For each 'C', add number of valid subsequences "L...C...T"
26                total += 1L * countL * countT;
27            }
28            if (c == 'L') {
29                countL++;
30            }
31            // Keep track of the maximum l * r for use later
32            maxVal = Math.max(maxVal, 1L * countL * countT);
33        }
34
35        // Also consider the maximum values for "LC" and "CT" subsequences
36        maxVal = Math.max(maxVal, Math.max(calc("LC"), calc("CT")));
37        total += maxVal;
38
39        return total;
40    }
41
42    // Helper method to count subsequences of type "ab" in the string
43    // For each 'b', add the current count of 'a' before it
44    private long calc(String pattern) {
45        long count = 0;
46        int countA = 0;
47        for (char c : s) {
48            if (c == pattern.charAt(1)) {
49                count += countA;
50            }
51            if (c == pattern.charAt(0)) {
52                countA++;
53            }
54        }
55        return count;
56    }
57}
58
1class Solution {
2public:
3    long long numOfSubsequences(string s) {
4        // Helper lambda to count subsequences "ab" in string s
5        auto countSubseq = [&](string ab) {
6            long long count = 0;
7            long long count_a = 0;
8            for (char c : s) {
9                if (c == ab[1]) {
10                    // For each 'b', add number of previous 'a's
11                    count += count_a;
12                }
13                if (c == ab[0]) {
14                    ++count_a;
15                }
16            }
17            return count;
18        };
19
20        long long count_L = 0;                        // Number of 'L's seen so far
21        long long count_T_remain = count(s.begin(), s.end(), 'T'); // Number of 'T's to the right
22        long long total = 0;                          // Accumulated answer
23        long long max_any_pattern = 0;                // Track the max of possible patterns
24
25        // Pass through the string to count the "L C T" triplet patterns
26        for (char c : s) {
27            if (c == 'T') {
28                --count_T_remain;
29            }
30            if (c == 'C') {
31                total += count_L * count_T_remain; // Count "L C T" for every 'C'
32            }
33            if (c == 'L') {
34                ++count_L;
35            }
36            // Track the max product of current counts for any update
37            max_any_pattern = max(max_any_pattern, count_L * count_T_remain);
38        }
39
40        // Consider the max of the pure pairs "LC" and "CT"
41        max_any_pattern = max(max_any_pattern, countSubseq("LC"));
42        max_any_pattern = max(max_any_pattern, countSubseq("CT"));
43
44        // Add the best possible extra pair to the overall answer
45        total += max_any_pattern;
46        return total;
47    }
48};
49
1/**
2 * Calculates the number of specific subsequences in a string.
3 * @param s Input string consisting of 'L', 'C', 'T'
4 * @returns Number of subsequences as per the logic
5 */
6function numOfSubsequences(s: string): number {
7    /**
8     * Helper function to count the number of subsequences
9     * for a given two-character pattern (first, second) in s.
10     * @param pattern String of length 2 (e.g., 'LC', 'CT')
11     * @returns Count of such subsequences in s
12     */
13    const calc = (pattern: string): number => {
14        let count = 0; // Count of subsequences found
15        let firstCharCount = 0; // Number of times pattern[0] has appeared so far
16
17        for (const c of s) {
18            if (c === pattern[1]) count += firstCharCount; // Every previous pattern[0] forms a subsequence
19            if (c === pattern[0]) firstCharCount++;        // Increment count of pattern[0] found
20        }
21        return count;
22    };
23
24    // Initial pass: count number of 'T' for use in next loop
25    let leftL = 0;     // Number of 'L's to the left (encountered so far)
26    let rightT = 0;    // Number of 'T's to the right (remaining)
27    for (const c of s) {
28        if (c === 'T') rightT++;
29    }
30
31    let answer = 0;    // The answer to be returned
32    let maxCombo = 0;  // Maximum number of valid subsequences involving 'L'...'C'...'T'
33
34    for (const c of s) {
35        if (c === 'T') rightT--;          // Decrement count when passing over 'T'
36        if (c === 'C') answer += leftL * rightT; // For every 'C', all previous 'L's and remaining 'T's form sequences
37        if (c === 'L') leftL++;           // Count encountered 'L's for later subsequences
38        maxCombo = Math.max(maxCombo, leftL * rightT); // Track largest L-T pairing after current index
39    }
40
41    // Calculate max subsequences from ('L','C') and ('C','T') pairs for optimal combination
42    maxCombo = Math.max(maxCombo, calc('LC'));
43    maxCombo = Math.max(maxCombo, calc('CT'));
44
45    answer += maxCombo; // Add maximum possible combinations from any single best pattern
46    return answer;
47}
48
49// Example usage (remove/comment when testing in actual LeetCode):
50// console.log(numOfSubsequences("LCTLTTC")); // Example test
51

Time and Space Complexity

The time complexity of the code is O(n), where n is the length of the string s. This is because the code performs several single-pass traversals over the string: once in the calc function (called at most twice), and once in the main loop. Each traversal takes linear time.

The space complexity is O(1), as only a constant number of integer variables are used to store counts and results, regardless of the input size.


Discover Your Strengths and Weaknesses: Take Our 2-Minute Quiz to Tailor Your Study Plan:

Which of the following uses divide and conquer strategy?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More