Given two strings a
and b
, return the minimum number of times you should repeat string a
so that string b
is a substring of it. If it is impossible for b
to be a substring of a
after repeating it, return -1
.
Notice: string "abc"
repeated 0 times is ""
, repeated 1 time is "abc"
and repeated 2 times is "abcabc"
.
Example 1:
Input: a = "abcd", b = "cdabcdab" Output: 3 Explanation: We return 3 because by repeating a three times "abcdabcdabcd", b is a substring of it.
Example 2:
Input: a = "a", b = "aa" Output: 2
Example 3:
Input: a = "a", b = "a" Output: 1
Example 4:
Input: a = "abc", b = "wxyz" Output: -1
Constraints:
1 <= a.length <= 104
1 <= b.length <= 104
a
andb
consist of lower-case English letters.
Related Topics:
String
Similar Questions:
We try to see if A * k
contains B
where k
is the answer. So we keep concatenating a
to an empty string s
until s
is not shorter than b
. Assume we repeated a
k
times.
- If
s
containsb
, then returnk
. - Otherwise, if
s + a
containsb
, returnk + 1
. - Otherwise, return
-1
.
// OJ: https://leetcode.com/problems/repeated-string-match/
// Author: github.com/lzl124631x
// Time: O(B * (A + B))
// Space: O(A + B)
// Ref: https://leetcode.com/problems/repeated-string-match/solution/
class Solution {
public:
int repeatedStringMatch(string a, string b) {
int k = 1;
string s = a;
for (; s.size() < b.size(); ++k) s += a;
if (s.find(b) != string::npos) return k;
return (s + a).find(b) != string::npos ? k + 1 : -1;
}
};
We keep finding B
in repeated A
string using Rabin-Karp algorithm (or Rolling Hash).
// OJ: https://leetcode.com/problems/repeated-string-match/
// Author: github.com/lzl124631x
// Time: O(A + B)
// Space: O(1)
class Solution {
unsigned prime = 16777619;
bool equal(string &a, string &b, unsigned offset) {
for (int i = 0; i < b.size(); ++i) {
if (a[(i + offset) % a.size()] != b[i]) return false;
}
return true;
}
pair<unsigned, unsigned> hashStr(string &s) {
unsigned h = 0, p = 1, sq = prime;
for (char c : s) h = h * prime + c;
for (int i = s.size(); i > 0; i >>= 1) {
if (i & 1) p *= sq;
sq *= sq;
}
return { h, p };
}
public:
int repeatedStringMatch(string a, string b) {
auto [hb, p] = hashStr(b);
unsigned A = a.size(), B = b.size(), ha = 0, i = 0;
for (; i < B; ++i) ha = ha * prime + a[i % A];
if (ha == hb && equal(a, b, 0)) return (i + A - 1) / A;
while (i < 2 * A + B) {
ha = ha * prime + a[i % A] - p * a[(i - B) % A];
++i;
if (ha == hb && equal(a, b, (i - B) % A)) return (i + A - 1) / A;
}
return -1;
}
};