重复叠加字符串匹配
- leetcode 686. 重复叠加字符串匹配
- 题目描述
- KMP 算法
- 代码演示
- KMP 算法
leetcode 686. 重复叠加字符串匹配
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/repeated-string-match
题目描述
给定两个字符串 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
提示:
1 <= a.length <= 10000
1 <= b.length <= 10000
a 和 b 由小写英文字母组成
KMP 算法
首先想明白一个问题,如果叠加后含有b,那么起始位置,一定是在a的某一个位置.
因此我们可以先复制出长度大于b字符串长度的字符串,然后根据kmp算法,看b是否是a叠加后的字串,就可以得出,得出需要复制的次数(在叠加时,记录叠加的次数).
代码演示
/**
* leetcode 686. 重复叠加字符串匹配
* @param a
* @param b
* @return
*/
public int repeatedStringMatch(String a, String b) {
StringBuilder sb = new StringBuilder();
int time = 0;
//当长度大于b 的长度时,就退出
while (sb.length() < b.length()){
time++;
sb.append(a);
}
sb.append(a);
int indexOf = getIndexOf(sb.toString(), b);
if (indexOf == -1){
return -1;
}
return indexOf + b.length() > a.length() * time ? time + 1 : time;
}
/**
* 判断s2 是否是 s1的子串. 返回出现的第一个字母的下标
* @param s1
* @param s2
* @return
*/
public int getIndexOf(String s1, String s2) {
if (s1 == null || s2 == null || s1.length() == 0 || s1.length() < s2.length()){
return -1;
}
char[] str1 = s1.toCharArray();
char[] str2 = s2.toCharArray();
int[] next = getNextArray(str2);
int x = 0;
int y = 0;
while (x < str1.length && y < str2.length){
if (str1[x] == str2[y]){
//相等时 去下一个位置去比较
x++;
y++;
} else if (next[y] == -1) {
x++;
}else {
y = next[y];
}
}
return y == str2.length ? x - y : -1;
}
/**
* 前缀和后缀相等的长度数组
* @param str
* @return
*/
public int[] getNextArray(char[] str){
if(str.length == 1){
return new int[]{-1};
}
int n = str.length;
int[] next = new int[n];
next[0] = -1;
next[1] = 0;
int i = 2;
int hc = 0;
while (i < n){
if (str[i - 1] == str[hc]){
next[i++] = ++hc;
} else if (hc > 0) {
hc = next[hc];
}else {
next[i++] = 0;
}
}
return next;
}
KMP 算法
KMP–高效字符串匹配算法