题目:
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.
代码:
#include<string>
class Solution {
public:
int repeatedStringMatch(string A, string B) {
string temp = "";
int cnt = B.size() / A.size() + 2;
int i = 0;
for(; i < cnt; i++){
temp += A;
if(temp.find(B) != string::npos) return i+1;
}
return -1;
}
};
class Solution {
public:
int repeatedStringMatch(string A, string B) {
// 思路1:i代表每次循环开始,A开始的位置(设想"abcd"、"cdabcd", 只有i=2才有可能比对成功)
/*for(int i = 0, j = 0; i < (int)A.size(); i++, j=0) {
while(j==-1 || (j < (int)B.size() && A[(i+j)%A.size()]==B[j])) ++j;
if(j == B.size()) {
// 此时 i 为 A 开始比对的位置,j显然是B的长度,如:
// A="abcd", B="cdabcdab", 则i=2, j=B.size()=8,可以发现刚好补上了前面的值,所以只需要判断是否有余数即可
return (i+j)/A.size()+((i+j)%A.size()!=0?1:0);
}
}*/
vector<int> next(B.size() + 1);
next[0] = -1;
for(int i = 0, j = -1; i < B.size(); ) {
if(j == -1 || B[j] == B[i]) next[++i] = ++j;
else j = next[j];
}
// 思路2:i的含义与思路1相同,代表每次循环开始,A开始的位置(哪怕是i=j-next[j])。
// 当next[j]>=0时,此时意味着j可以跳过某些重复比对,直接从next[j]开始。
//
// 关键在于:如何判断无论如何加倍A,也无法构成题目要求的串?
// 当i>=A.size()时,则可以认为无需再比对下去。因为如果i>=A.size(),其实取模后的值本应该早就比对过了
for(int i = 0, j = 0; i < (int)A.size(); i+=max(1,j-next[j]), j=next[j]) {
while(j==-1 || (j < (int)B.size() && A[(i+j)%A.size()]==B[j])) ++j;
if(j == B.size()) {
// 此时 i 为 A 开始比对的位置,j显然是B的长度,如:
// A="abcd", B="cdabcdab", 则i=2, j=B.size()=8,可以发现刚好补上了前面的值,所以只需要判断是否有余数即可
return (i+j)/A.size()+((i+j)%A.size()!=0?1:0);
}
}
return -1;
}
};