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

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

<p>For example, <strong>one way</strong> to encode an original string <code>&quot;abcdefghijklmnop&quot;</code> might be:</p>

<ul>
	<li>Split it as a sequence: <code>[&quot;ab&quot;, &quot;cdefghijklmn&quot;, &quot;o&quot;, &quot;p&quot;]</code>.</li>
	<li>Choose the second and third elements to be replaced by their lengths, respectively. The sequence becomes <code>[&quot;ab&quot;, &quot;12&quot;, &quot;1&quot;, &quot;p&quot;]</code>.</li>
	<li>Concatenate the elements of the sequence to get the encoded string: <code>&quot;ab121p&quot;</code>.</li>
</ul>

<p>Given two encoded strings <code>s1</code> and <code>s2</code>, consisting of lowercase English letters and digits <code>1-9</code> (inclusive), return <code>true</code><em> if there exists an original string that could be encoded as <strong>both</strong> </em><code>s1</code><em> and </em><code>s2</code><em>. Otherwise, return </em><code>false</code>.</p>

<p><strong>Note</strong>: The test cases are generated such that the number of consecutive digits in <code>s1</code> and <code>s2</code> does not exceed <code>3</code>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

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

<p><strong class="example">Example 2:</strong></p>

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

<p><strong class="example">Example 3:</strong></p>

<pre>
<strong>Input:</strong> s1 = &quot;a5b&quot;, s2 = &quot;c5b&quot;
<strong>Output:</strong> false
<strong>Explanation:</strong> It is impossible.
- The original string encoded as s1 must start with the letter &#39;a&#39;.
- The original string encoded as s2 must start with the letter &#39;c&#39;.
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= s1.length, s2.length &lt;= 40</code></li>
	<li><code>s1</code> and <code>s2</code> consist of digits <code>1-9</code> (inclusive), and lowercase English letters only.</li>
	<li>The number of consecutive digits in <code>s1</code> and <code>s2</code> does not exceed <code>3</code>.</li>
</ul>

class Solution:
    def possiblyEquals(self, s1: str, s2: str) -> bool:
        def routine2(big, f, small, s1, s2, seq):
            for i in range(small, min(small + 3, len(s2))):
                if s2[i].isalpha():
                    break
                newf = int(s2[small:i+1])
                diff1 = max(0, f - newf)
                diff2 = max(0, newf - f)
                valid = match(big, diff1, i+1, diff2) if seq else match(i+1, diff2, big, diff1)
                if valid:
                    return True
            return False
        # Delete until a number is seen
        def routine1(big, f, small, s1, s2, seq):

            while f > 0 and small < len(s2) and s2[small].isalpha():
                small += 1
                f -= 1
            # print("routine 1, " ,big, f, small, s1, s2, seq)
            if small == len(s2):
                return f == 0 and big == len(s1)
            elif f == 0:
                return match(big, 0, small, 0) if seq else match(small, 0, big, 0)
            return routine2(big, f, small, s1, s2, seq)
                

        @cache
        def match(a, fa, b, fb):
            # if a == len(s1) and b == len(s2):
            #     return fa == fb == 0
            # elif a == len(s1) or b == len(s2):
            #     return False
            if fa > 0:
                return routine1(a, fa, b, s1, s2, True)
            elif fb > 0:
                return routine1(b, fb, a, s2, s1, False)
            if fa == fb == 0:
                while a < len(s1) and b < len(s2) and ((s1[a] + s2[b]).isalpha()):
                    if s1[a] != s2[b]:
                        return False
                    a += 1
                    b += 1
                if (a == len(s1) and b == len(s2)):
                    return True
                if a == len(s1) or b == len(s2):
                    return False
                if s1[a].isnumeric() and not s2[b].isnumeric():
                    return routine2(b, 0, a, s2, s1, False)
                elif s2[b].isnumeric() and not s1[a].isnumeric():
                    return routine2(a, 0, b, s1, s2, True)
                # both are looking at numbers
                for endA in range(a, min(a + 3, len(s1))):
                    if not s1[endA].isnumeric():
                        break
                    for endB in range(b, min(b + 3, len(s2))):
                        if not s2[endB].isnumeric():
                            break
                        diff = int(s1[a:endA + 1]) - int(s2[b:endB + 1])
                        fa = max(0, diff)
                        fb = max(0, -1 * diff)
                        if match(endA + 1, fa, endB + 1, fb):
                            return True
                return False
        return match(0, 0, 0, 0)
979