题目:重复叠加字符串匹配
给定两个字符串 a 和 b,寻找重复叠加字符串 a 的最小次数,使得字符串 b 成为叠加后的字符串 a 的子串,如果不存在则返回 -1。
注意: 字符串 "abc" 重复叠加 0 次是 "",重复叠加 1 次是 "abc",重复叠加 2 次是 "abcabc"。
示例 1:
输入: a = "abcd", b = "cdabcdab"
输出: 3
解释: a 重复叠加三遍后为 "abcdabcdabcd", 此时 b 是其子串。
示例 2:
输入: a = "a", b = "aa"
输出: 2
示例 3:
输入: a = "a", b = "a"
输出: 1
示例 4:
输入: a = "abc", b = "wxyz"
输出: -1
提示:
a和b由小写英文字母组成
解题思路
来个非常简单的模拟,虽然速度比不上,但是思考比较简单
使用一个StringBuilder sb作为a累加的效果,在每次累加a的时候,都与b进行比较,看b是否是sb的子串
注意sb的的最大长度,为b.length() + a.length() * 2; 因为a累加最极端情况下,第一个a的最后一个字母,与最后一个a的第一个字母参与将b作为子串,
使用KMP查找a是否是b的字串,如果返回值 >= 0 ,说明a 是 b 的字串; 当a 是 b的字串时,假设b中 b[left]...b[right]为a. 之后 从b[left-1]..b[0]开始判断是否和 a的倒叙一致,就对a进行倒叙遍历,如果出现不一致的情况,return -1, 否则遍历完a的前缀,left = 1; 之后 从b[right+1]..b[length-1]开始判断是否和 a的顺序一致,就对a进行顺序遍历,如果出现不一致的情况,return -1, 否则遍历完a的前缀,记录right(right可能大于1); 此时返回值为 left + right + 1; 当a不是b的字串时,判断b是否为a的字串。此时将a翻倍,令 c = a + a,然后使用KMP查找b是否是c的字串,返回值 = -1 , return -1;当返回值 >= 0时,判断 index 是否大于 aStr.length,判断成立说明需要两个a才能拼成b,return 2,否则return 1;
给定两个字符串 a 和 b,寻找重复叠加字符串 a 的最小次数,使得字符串 b 成为叠加后的字符串 a 的子串,如果不存在则返回 -1。 b若是a叠加若干次之后的子串。
代码实现
public int repeatedStringMatch(String a, String b) {
int[] count = new int[26];
//判断是否有字符k,存在于b,但不存在于a
for (int i = 0; i < a.length(); i++) {
count[a.charAt(i) - 'a'] ++;
}
for (int i = 0; i < b.length(); i++) {
if (count[b.charAt(i) - 'a'] == 0) return -1;
}
//依次遍历a的每个字符
for (int i = 0; i < a.length(); i++) {
//当a的某个字符和b的头字符相同,开始比对
if (a.charAt(i) == b.charAt(0)) {
int start = i;
int j = 0;
while (j < b.length()) {
if (a.charAt(start % a.length()) != b.charAt(j)) break;
j++;
start++;
}
//比对成功,输出结果
if (j == b.length()) {
int ans = start / a.length();
if (start % a.length() != 0) ans++;
return ans;
}
}
}
return -1;
}
运行结果
复杂度分析
- 空间复杂度:O(n)
- 时间复杂度:O(n)
在掘金(JUEJIN) 一起分享知识, Keep Learning!