<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:
        return self.fun4(s1, n1, s2, n2)

    def fun4(self, s1, n1, s2, n2):
        ns1 = len(s1)
        ns2 = len(s2)

        dp = {}
        cnt1, cnt2, i1, i2 = 1, 0, 0, 0

        while True:
            if s1[i1] == s2[i2]:
                if i2 == ns2 - 1:
                    cnt2 += 1
                    i2 = 0
                    if i1 in dp:
                        left = dp[i1]
                        mid = (cnt1 - dp[i1][0], cnt2 - dp[i1][1])
                        break
                    else:
                        dp[i1] = (cnt1, cnt2)
                else:
                    i2 += 1

            if i1 == ns1 - 1:
                if cnt1 == n1:
                    return cnt2 // n2
                i1 = 0
                cnt1 += 1
            else:
                i1 += 1

        res = left[1] + (n1 - left[0]) // mid[0] * mid[1]
        rest = (n1 - left[0]) % mid[0]
        srest = s1[i1 + 1 :] + s1 * rest
        # i2 = 0
        for c in srest:
            if c == s2[i2]:
                if i2 == ns2 - 1:
                    res += 1
                    i2 = 0
                else:
                    i2 += 1

        return res // n2

    def fun3(self, s1, n1, s2, n2):
        ns1 = len(s1)
        ns2 = len(s2)
        # dp[i] = (next, cnt) 表示s2第i字母开始和s1比对完的cnt数量以及s2下一个比对的next字母位置
        dp = {}
        res = 0
        st = 0
        for i in range(n1):
            if st in dp:
                cnt, nxt = dp[st]
                res += cnt
                st = nxt
            else:
                cnt = 0
                k = st
                for j in range(ns1):
                    if s1[j] == s2[k]:
                        if k == ns2 - 1:
                            cnt += 1
                            k = 0
                        else:
                            k += 1
                dp[st] = (cnt, k)
                res += cnt
                st = k

        return res // n2

    def fun2(self, s1, n1, s2, n2):
        ns1 = len(s1)
        ns2 = len(s2)
        # dp[i] = (next, cnt) 表示s2第i字母开始和s1比对完的cnt数量以及s2下一个比对的next字母位置
        dp = [(0, 0) for _ in range(ns2)]
        for i in range(ns2):
            st = i
            cnt = 0
            for j in range(ns1):
                if s1[j] == s2[st]:
                    if st == ns2 - 1:
                        cnt += 1
                        st = 0
                    else:
                        st += 1
            dp[i] = (st, cnt)

        res = 0
        st = 0
        for i in range(n1):
            st, cnt = dp[st]
            res += cnt
        return res // n2

    def fun1(self, s1: str, n1: int, s2: str, n2: int) -> int:
        str1 = s1 * n1
        str2 = s2 * n2

        j = 0
        ns2 = len(str2) - 1
        res = 0
        for c1 in str1:
            if str2[j] == c1:
                if j == ns2:
                    res += 1
                    j = 0
                else:
                    j += 1

        return res


16900