Skip to content

2014. Longest Subsequence Repeated k Times

Description

You are given a string s of length n, and an integer k. You are tasked to find the longest subsequence repeated k times in string s.

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

A subsequence seq is repeated k times in the string s if seq * k is a subsequence of s, where seq * k represents a string constructed by concatenating seq k times.

  • For example, "bba" is repeated 2 times in the string "bababcba", because the string "bbabba", constructed by concatenating "bba" 2 times, is a subsequence of the string "bababcba".

Return the longest subsequence repeatedk times in string s. If multiple such subsequences are found, return the lexicographically largest one. If there is no such subsequence, return an empty string.

 

Example 1:

example 1
Input: s = "letsleetcode", k = 2
Output: "let"
Explanation: There are two longest subsequences repeated 2 times: "let" and "ete".
"let" is the lexicographically largest one.

Example 2:

Input: s = "bb", k = 2
Output: "b"
Explanation: The longest subsequence repeated 2 times is "b".

Example 3:

Input: s = "ab", k = 2
Output: ""
Explanation: There is no subsequence repeated 2 times. Empty string is returned.

 

Constraints:

  • n == s.length
  • 2 <= n, k <= 2000
  • 2 <= n < k * 8
  • s consists of lowercase English letters.

 

Solutions

Solution: Breadth-First Search

  • Time complexity: O(n*possibleChars.lengthn/k)
  • Space complexity: O(possibleChars.lengthn/k)

 

JavaScript

js
/**
 * @param {string} s
 * @param {number} k
 * @return {string}
 */
const longestSubsequenceRepeatedK = function (s, k) {
  const BASE_CODE = 'a'.charCodeAt(0);
  const counts = Array.from({ length: 26 }, () => 0);
  const possibleChars = [];
  const queue = [''];
  let result = '';

  for (const char of s) {
    const code = char.charCodeAt(0) - BASE_CODE;

    counts[code] += 1;
  }

  for (let index = 0; index < 26; index++) {
    if (counts[index] < k) continue;
    const char = String.fromCharCode(index + BASE_CODE);

    possibleChars.push(char);
  }

  const isValidSubseq = (subseq, times) => {
    let index = 0;

    for (const char of s) {
      if (subseq[index] === char) {
        index += 1;
      }

      if (index === subseq.length) {
        times -= 1;
        index = 0;
      }

      if (times === 0) return true;
    }

    return false;
  };

  while (queue.length) {
    const currentSubseq = queue.shift();

    for (const char of possibleChars) {
      const nextSubSeq = `${currentSubseq}${char}`;

      if (isValidSubseq(nextSubSeq, k)) {
        queue.push(nextSubSeq);
        result = nextSubSeq;
      }
    }
  }

  return result;
};

Released under the MIT license