Great solution!

I have a minor optimization. In order to remove the inner loop to search for nextIndex[start], which is O(n^2) and n is s2.size(), we can use a hash table visited[k]. It is used to record how many passes of s1 is required to get nextIndex of k. For example, visited[2] = p means after p passes of s1, the index in string s2 is 2. And the vector<int> nextIndex is not necessary any more.

Also prefixCount + suffixCount = repeatCount[start + (n1 - start) % (k - start)], which can be simplified.

class Solution {
public:
int getMaxRepetitions(string s1, int n1, string s2, int n2) {
int m1 = s1.size(), m2 = s2.size();
vector<int> repeated(m2+1,0), visited(m2+1, -1);
visited[0] = 0;
int k = 0, cnt = 0;
for (int i = 1; i <= n1; i++) {
for (int j = 0; j < m1; j++) {
if (s1[j] == s2[k]) {
k++;
if (k == m2) {
k = 0;
cnt++;
}
}
}
if (visited[k] == -1) {
repeated[i] = cnt;
visited[k] = i;
}
else {
int start = visited[k], p = i-start, t = cnt-repeated[start];
int ans = (n1-start)/p*t + repeated[(n1-start)%p+start];
return ans/n2;
}
}
return cnt/n2;
}
};