Skip to content

2060. Check if an Original String Exists Given Two Encoded Strings

Description

An original string, consisting of lowercase English letters, can be encoded by the following steps:

  • Arbitrarily split it into a sequence of some number of non-empty substrings.
  • Arbitrarily choose some elements (possibly none) of the sequence, and replace each with its length (as a numeric string).
  • Concatenate the sequence as the encoded string.

For example, one way to encode an original string "abcdefghijklmnop" might be:

  • Split it as a sequence: ["ab", "cdefghijklmn", "o", "p"].
  • Choose the second and third elements to be replaced by their lengths, respectively. The sequence becomes ["ab", "12", "1", "p"].
  • Concatenate the elements of the sequence to get the encoded string: "ab121p".

Given two encoded strings s1 and s2, consisting of lowercase English letters and digits 1-9 (inclusive), return true if there exists an original string that could be encoded as boths1 and s2. Otherwise, return false.

Note: The test cases are generated such that the number of consecutive digits in s1 and s2 does not exceed 3.

 

Example 1:

Input: s1 = "internationalization", s2 = "i18n"
Output: true
Explanation: It is possible that "internationalization" was the original string.
- "internationalization" 
  -> Split:       ["internationalization"]
  -> Do not replace any element
  -> Concatenate:  "internationalization", which is s1.
- "internationalization"
  -> Split:       ["i", "nternationalizatio", "n"]
  -> Replace:     ["i", "18",                 "n"]
  -> Concatenate:  "i18n", which is s2

Example 2:

Input: s1 = "l123e", s2 = "44"
Output: true
Explanation: It is possible that "leetcode" was the original string.
- "leetcode" 
  -> Split:      ["l", "e", "et", "cod", "e"]
  -> Replace:    ["l", "1", "2",  "3",   "e"]
  -> Concatenate: "l123e", which is s1.
- "leetcode" 
  -> Split:      ["leet", "code"]
  -> Replace:    ["4",    "4"]
  -> Concatenate: "44", which is s2.

Example 3:

Input: s1 = "a5b", s2 = "c5b"
Output: false
Explanation: It is impossible.
- The original string encoded as s1 must start with the letter 'a'.
- The original string encoded as s2 must start with the letter 'c'.

 

Constraints:

  • 1 <= s1.length, s2.length <= 40
  • s1 and s2 consist of digits 1-9 (inclusive), and lowercase English letters only.
  • The number of consecutive digits in s1 and s2 does not exceed 3.

 

Solutions

Solution: Dynamic Programming

  • Time complexity: O(n1*n2*1000)
  • Space complexity: O(n1*n2*1000)

 

JavaScript

js
/**
 * @param {string} s1
 * @param {string} s2
 * @return {boolean}
 */
const possiblyEquals = function (s1, s2) {
  const n1 = s1.length;
  const n2 = s2.length;
  const dp = Array.from({ length: n1 + 1 }, () => {
    return new Array(n2 + 1)
      .fill('')
      .map(() => new Map());
  });

  const isNumber = char => Number.isInteger(Number(char));

  const findNextLetter = (s, index) => {
    while (index < s.length && isNumber(s[index])) {
      index += 1;
    }

    return index;
  };

  const getPaddings = num => {
    const n = num.length;
    const nums = [Number(num)];

    if (n === 2) {
      const [a, b] = num;

      nums.push(Number(a) + Number(b));
    }

    if (n === 3) {
      const [a, b, c] = num;
      const num1 = Number(a) + Number(b) + Number(c);
      const num2 = Number(a) + Number(`${b}${c}`);
      const num3 = Number(`${a}${b}`) + Number(c);

      nums.push(num1, num2, num3);
    }

    return nums;
  };

  const isPossiblyEncode = (a, b, padding) => {
    if (a === n1 && b === n2) return padding === 0;
    if (dp[a][b].has(padding)) return dp[a][b].get(padding);

    if (a < n1 && isNumber(s1[a])) {
      const index = findNextLetter(s1, a);
      const nums = getPaddings(s1.slice(a, index));

      for (const num of nums) {
        if (isPossiblyEncode(index, b, padding + num)) {
          dp[a][b].set(padding, true);

          return true;
        }
      }
    } else if (b < n2 && isNumber(s2[b])) {
      const index = findNextLetter(s2, b);
      const nums = getPaddings(s2.slice(b, index));

      for (const num of nums) {
        if (isPossiblyEncode(a, index, padding - num)) {
          dp[a][b].set(padding, true);

          return true;
        }
      }
    } else if (padding < 0) {
      if (a < n1 && isPossiblyEncode(a + 1, b, padding + 1)) {
        dp[a][b].set(padding, true);

        return true;
      }
    } else if (padding > 0) {
      if (b < n2 && isPossiblyEncode(a, b + 1, padding - 1)) {
        dp[a][b].set(padding, true);

        return true;
      }
    } else if (a < n1 && b < n2 && s1[a] === s2[b] && isPossiblyEncode(a + 1, b + 1, 0)) {
        dp[a][b].set(padding, true);

        return true;
      }

    dp[a][b].set(padding, false);

    return false;
  };

  return isPossiblyEncode(0, 0, 0);
};

Released under the MIT license