<p>We define <code>str = [s, n]</code> as the string <code>str</code> which consists of the string <code>s</code> concatenated <code>n</code> times.</p>

<ul>
	<li>For example, <code>str == [&quot;abc&quot;, 3] ==&quot;abcabcabc&quot;</code>.</li>
</ul>

<p>We define that string <code>s1</code> can be obtained from string <code>s2</code> if we can remove some characters from <code>s2</code> such that it becomes <code>s1</code>.</p>

<ul>
	<li>For example, <code>s1 = &quot;abc&quot;</code> can be obtained from <code>s2 = &quot;ab<strong><u>dbe</u></strong>c&quot;</code> based on our definition by removing the bolded underlined characters.</li>
</ul>

<p>You are given two strings <code>s1</code> and <code>s2</code> and two integers <code>n1</code> and <code>n2</code>. You have the two strings <code>str1 = [s1, n1]</code> and <code>str2 = [s2, n2]</code>.</p>

<p>Return <em>the maximum integer </em><code>m</code><em> such that </em><code>str = [str2, m]</code><em> can be obtained from </em><code>str1</code>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<pre><strong>Input:</strong> s1 = "acb", n1 = 4, s2 = "ab", n2 = 2
<strong>Output:</strong> 2
</pre><p><strong class="example">Example 2:</strong></p>
<pre><strong>Input:</strong> s1 = "acb", n1 = 1, s2 = "acb", n2 = 1
<strong>Output:</strong> 1
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= s1.length, s2.length &lt;= 100</code></li>
	<li><code>s1</code> and <code>s2</code> consist of lowercase English letters.</li>
	<li><code>1 &lt;= n1, n2 &lt;= 10<sup>6</sup></code></li>
</ul>

class Solution:
    def getMaxRepetitions(self, s1: str, n1: int, s2: str, n2: int) -> int:
        l1, l2 = len(s1), len(s2)
        chars = set(s1)
        for c in s2:
            if c not in chars:
                return 0
        
        jumps = []
        def getchar(ofs):
            return s1[ofs % l1]
        
        for i in range(l1):
            cur = i
            for c in s2:
                while getchar(cur) != c:
                    cur += 1
                cur += 1
            jumps.append(cur - i)
        
        dp = {}
        def jumplen_pow2(rem, pow2):
            assert(rem >= 0 and rem < l1)
            key = (rem, pow2)
            if key in dp:
                return dp[key]
            if pow2 == 1:
                r = jumps[rem]
            else:
                pow2 >>= 1
                r = jumplen(rem, pow2)
                r += jumplen((rem + r) % l1, pow2)
            dp[key] = r
            return r
        
        def jumplen(rem, m):
            if m == 0:
                return 0
            pow2 = 1
            jl = 0
            while pow2 <= m:
                if pow2 & m:
                    l = jumplen_pow2(rem, pow2)
                    jl += l
                    rem = (rem + l) % l1
                pow2 <<= 1
            return jl
        
        limit = l1 * n1
        m = 1
        prev = 0
        while jumplen_pow2(0, m) <= limit:
            prev = m
            m <<= 1
        
        l, r = prev, m
        while r - l > 1:
            m = l + (r - l) // 2
            if jumplen(0, m) <= limit:
                l = m
            else:
                r = m
        
        return l // n2

17400