Easy-understanding Java Solution with detailed explanation, 21ms!
The key is, we just need to calculate what will remain after s1 obtains s2.\n\nThat is, (s1, s2) -> (sRemain, matchCnt); for example,\n(abcd, ab) -> (cd, 1)\n(a
The key is, we just need to calculate ***what will remain after s1 obtains s2***.\n\nThat is, `(s1, s2) -> (sRemain, matchCnt)`; for example,\n`(abcd, ab) -> (cd, 1)`\n`(ababa, ab) -> (a, 2)`\n`(a, aaaa) -> (a, 0)`\n`(aabaabaab, aba) -> (ab, 2)` as `aabaaba` exactly matches `aba` twice.\n\n\nAnd, each time we append `s1` to the `remain string`, to make a sequence: (Using `[]` to mark the `remain string`)\n`(abcd, ab): abcd -> [cd]abcd -> [cd]abcd -> [cd]abcd -> ...`\n`(ababa, ab): ababa -> [a]ababa -> [a]ababa -> [a]ababa -> ...`\n`(a, aaaa): a -> [a]a -> [aa]a -> [aaa]a -> a -> [a]a -> [aa]a -> ...`\n`(aabaabaab, aba): aabaabaab -> [ab]aabaabaab -> [ab]aabaabaab -> ...`\n\nObviously, there will be a loop in the sequence, assume the length of loop is `loop`, and the length before the loop is `k`.\n`(abcd, ab): loop=1, k=1`\n`(a, aaaa): loop=4, k=0`\n`(aabaabaab, aba): loop=1, k=1`\n\nSo, we just need to calculate `the count of each loop`, and `the count before entering the loop`, and calculate the total.\n\nHere is the code with detailed comment, 21ms.\n\n```\npublic class Solution {\n    public int getMaxRepetitions(String s1, int n1, String s2, int n2) {\n        if (!ableToObtain(s1, s2)) return 0; // check if [s1. \u221e] obtains s2\n        int cnt=0, k=-1;\n        String s=s1;\n        StringBuilder remainBuilder; // record `remain string`\n        ArrayList<String> stringList=new ArrayList<>(); // record all the `remain string`\n        ArrayList<Integer> countList=new ArrayList<>(); // record matching count from start to the current remain string \n        stringList.add(""); // record empty string\n        countList.add(0);\n        for (int i=0;i<=n1;i++) {\n            remainBuilder=new StringBuilder();\n            cnt+=getRemain(s, s2, remainBuilder); // get the next remain string, returns the count of matching\n            String remain=remainBuilder.toString();\n            if ((k=stringList.indexOf(remain))!=-1) break; // if there is a loop, break\n            stringList.add(remain); // record the remain string into arraylist \n            countList.add(cnt);\n            s=remain+s1; // append s1 to make a new string\n        }\n        // here, k is the beginning of the loop\n        if (k==-1) return cnt/n2; // if there is no loop\n        int countOfLoop=cnt-countList.get(k), loopLength=stringList.size()-k; // get matching count in the loop, and loop length\n        cnt=countList.get(k);\n        n1-=k;\n        cnt+=countOfLoop*(n1/loopLength);\n        n1%=loopLength; \n        cnt+=countList.get(k+n1)-countList.get(k);\n        return cnt/n2;\n    }\n\n    // check if [s1. \u221e] obtains s2\n    private boolean ableToObtain(String s1, String s2) {\n        boolean[] cnt=new boolean[26];\n        for (char c: s1.toCharArray()) cnt[c-'a']=true;\n        for (char c: s2.toCharArray()) {\n            if (!cnt[c-'a']) return false;\n        }\n        return true;\n    }\n\n    // get remain string after s1 obtains s2, return the matching count\n    private int getRemain(String s1, String s2, StringBuilder remain) {\n        int cnt=0, lastMatch=-1, p2=0;\n        for (int p1=0;p1<s1.length();p1++) {\n            if (s1.charAt(p1)==s2.charAt(p2)) {\n                if (++p2==s2.length()) {\n                    p2=0;\n                    cnt++;\n                    lastMatch=p1;\n                }\n            }\n        }\n        remain.append(s1.substring(lastMatch+1));\n        return cnt;\n    }\n}\n```
[]