#LeetCode 28. Find the Index of the First Occurrence in a String
#LeetCode 28. 视频讲解:帮你把KMP算法学个通透!(求next数组代码篇)_哔哩哔哩_bilibili
KMP算法:主要是解决一个字符串中是否出现了另一个字符串的问题。
前缀:包括首字母但不包含尾字母的所有前缀,例如:abca,前缀是:a, ab, abc 。
后缀:包括尾字母但不包含首字母的所有后缀,例如:abca,后缀是:a, ca, bca 。KMP算法是找到最长相等的前后缀,例如:在aabaa 中,最长相等前后缀为aa 。
如果出现不匹配时,会指向前一个元素的最长相等前后缀。如下图,最后一个f 不匹配,那么在f 之前最长相等前后缀 = 2 ,这意味着前面的aabaa 存在两个元素相匹配,那么可以在第三个元素继续比较,达到降低时间复杂度的目的。
用到的参数:i 代表后缀的末尾,j 代表前缀末尾(同样是最长相等前后缀),next 数组来记录每个元素的最长相等前后缀。在初始状态下,j = 0 ,i = 1 ,next[0] = 0 (因为第一个元素即使前缀又是后缀,所以不存在最长相等前后缀)。函数考虑两种情况:前后缀不相同情况、前后缀情况。前后缀不相同情况,则用while - loop ,j 一直向前移动,直到找到相同的元素。前后缀相同情况,那么更新next 数组。每次比较needle[i] == needle[j] 是在比较[0, j] 这个子字符串是否存在相同的后缀,如果不相同,j 会向前移动,重新比较。
完成getNext() 函数后,是用于实现计算next 数组,在strStr 函数中依然要用相同思路比较。
KMP 方法代码:
class Solution {
public int strStr(String haystack, String needle) {
if (needle.length() == 0) {
return 0;
}
int[] next = new int[needle.length()];
getNext(next, needle);
for (int i = 0, j = 0; i < haystack.length(); i++) {
while (j > 0 && haystack.charAt(i) != needle.charAt(j)) {
j = next[j - 1];
}
if (haystack.charAt(i) == needle.charAt(j)){
j++;
}
if (needle.length() == j) {
return i - needle.length() + 1;
}
}
return -1;
}
public void getNext(int[] next, String s) {
int i, j = 0;
next[0] = 0;
for (i = 1; i < s.length(); i++) {
while(j > 0 && s.charAt(i) != s.charAt(j)) {
j = next[j - 1];
}
if (s.charAt(i) == s.charAt(j)) {
j++;
}
next[i] = j;
}
}
}
#LeetCode 459. Repeated Substring Pattern
#LeetCode 459. 视频讲解:字符串这么玩,可有点难度! | LeetCode:459.重复的子字符串_哔哩哔哩_bilibili
如何判断重复数组: 最小重复子串 = 最长相等前后缀不包含的部分。
在找到最长相等前后缀后,用字符串的长度减去最长相等前后缀即为最小重复子串。看字符串长度是否能整除最小重复子串来判断。
KMP 方法代码:
class Solution {
public boolean repeatedSubstringPattern(String s) {
if (s.length() == 0) {
return false;
}
int[] next = new int[s.length()];
getNext(next, s);
int length = s.length() - next[s.length() - 1];
if (s.length() % length == 0 && next[s.length() - 1] > 0) {
return true;
}
else return false;
}
public void getNext(int[] next, String s) {
next[0] = 0;
int i = 0;
int j;
for (j = 1; j < s.length(); j++) {
while (i > 0 && s.charAt(i) != s.charAt(j)) {
i = next[i - 1];
}
if (s.charAt(i) == s.charAt(j)) {
i++;
}
next[j] = i;
}
}
}