问题:
Given two strings A and B, find the minimum number of times A has to be repeated such that B is a substring of it. If no such solution, return -1.
For example, with A = "abcd" and B = "cdabcdab".
Return 3, because by repeating A three times (“abcdabcdabcd”), B is a substring of it; and B is not a substring of A repeated two times ("abcdabcd").
Note:
The length of A
and B
will be between 1 and 10000.
解决:
① 用字符串B匹配字符串A,问字符串A需要重复几次,如果无法匹配,则返回-1。
B要能成为A的子串,那么A的长度肯定要大于等于B,所以当A的长度小于B的时候,我们可以先进行重复A,直到A的长度大于等于B,并且累计次数count。
然后看B是否存在A中,如果存在直接返回count。如果不存在,我们再加上一个A,再来找,这样可以处理这种情况A="abc", B="cab",如果此时还找不到,说明无法匹配,返回-1。
class Solution{ //190ms
public int repeatedStringMatch(String A, String B) {
int count = 0;
StringBuilder sb = new StringBuilder();
while (sb.length() < B.length()) {
sb.append(A);
count ++;
}
if(sb.toString().contains(B)) return count;
if(sb.append(A).toString().contains(B)) return ++ count;
return -1;
}
}
② 思路和上面的一样,都是每次给t增加一个字符串A,每次增加B的长度除以A的长度再加上2,当B小于A的时候,那么可能需要两个A,所以i就是小于等于2,这样我们每次在t中找B,如果找到了,就返回i,没找到,就增加一个A,循环退出后返回-1即可。
class Solution { //263ms
public int repeatedStringMatch(String A, String B) {
int len1 = A.length();
int len2 = B.length();
int count = 1;
String tmp = A;
for (int i = 1;i <= len2 / len1 + 2;i ++){
if (tmp.contains(B)) return i;
tmp += A;
}
return -1;
}
}
③ KMP算法
class Solution {//12ms
public int repeatedStringMatch(String a, String b) {
int[] prefTable=new int[b.length() + 1];
char A[]=a.toCharArray();
char B[]=b.toCharArray();
for (int i = 1, j = 0; i < b.length(); prefTable[++i] = j){
//j = B[j] == B[suffix] ? j + 1 : prefTable[j];
if(B[j] == B[i])
j=j + 1;
else
j=prefTable[j];
}
for (int i = 0, j = 0; i < a.length(); i += Math.max(1, j - prefTable[j]), j = prefTable[j]) {
while (j < b.length() && A[(i + j) % a.length()] == B[j]) ++j;
if (j == b.length())
return (i + j) / a.length() + ((i + j) % a.length() != 0 ? 1 : 0);
}
return -1;
}
}