目录
LeetCode 28.实现strStr()
文章讲解:代码随想录
视频讲解:帮你把KMP算法学个通透!(理论篇)_哔哩哔哩_bilibili
滑动窗口的思路:
1.首先获取haystack的长度和needle的长度
2.做一个剪枝的操作,如果needle的长度等于0,返回0;如果haystack的长度小于needle的长度,说明在haystack中是不可能找出needle,返回-1;
3.在循环的次数上也可以做一个剪枝的操作,因为是要在haystack中找到needle,所以在符合以上的条件下,循环的次数就只能是haystack的长度减去needle的长度加一,为什么要加一?举个例子,假设haystack的长度为5,needle的长度为3,那么在haystack中找needle就只有012,123,234三种情况,所以循环的次数就只是haystack的长度减去needle的长度加一。
4.在haystack中寻找与needle第一个字符相等的位置
5.此时,指向haystack中的字符与指向needle中的字符不断进行比较
6.最后,对跳出循环的needle下标和needle的长度进行比较。
代码如下(滑动窗口):Java
class Solution {
public int strStr(String haystack, String needle) {
int needleLength = needle.length();
if(needleLength == 0) return 0;
int haystackLength = haystack.length();
if(haystackLength < needleLength) return -1;
int i = 0;
int j = 0;
while(i < haystackLength - needleLength + 1){
while(i < haystackLength && haystack.charAt(i) != needle.charAt(j)){
i++;
}
if((haystackLength - i) < needleLength) return -1;
i++;
j++;
while(i < haystackLength && j < needleLength && haystack.charAt(i) == needle.charAt(j)){
i++;
j++;
}
if(j == needleLength) return i - j;
else{
i -= j - 1;
j = 0;
}
}
return -1;
}
}
代码如下(暴力解法):
class Solution {
public int strStr(String haystack, String needle) {
int a = haystack.length();
int b = needle.length();
for(int i = 0; i + b <= a; i++){
boolean flag = true;
for(int j = 0; j < b; j++){
if(haystack.charAt(i + j) != needle.charAt(j)){
flag = false;
break;
}
}
if(flag){
return i;
}
}
return -1;
}
}
kmp算法思路:
1.理解kmp算法的作用、特点。
2.next数组作用:当匹配的字符不同时,利用next数组来定位最近的字符。
3.构建next数组:①对j进行初始化,j既是存储最长前后缀的值,也是判断字符不同时根据j的值来进行回退。②对next数组进行初始化。③字符不同时,对j进行处理。④字符相同时,对j进行处理。⑤对next数组进行填充。
4.构建next数组完成后,回到主程序中。用i指向haystack字符串,用j来指向needle字符串且j代表的是匹配字符的长度。用for循环来遍历haysack字符串,在循环的过程中,当判断字符不相同的情况时,j利用next数组来进行回退;当判断字符相同时,j指向下一位也代表符合字符的长度加一。最后当j等于needle的长度时,就证明已经判断needle字符串是在haystack中,此时把i + 1 - j就可以得到所匹配的最开始位置。
代码如下(kmp解法,不减一):
class Solution {
public int strStr(String haystack, String needle) {
if(needle.length() == 0){
return 0;
}
int j = 0;
int[] next = new int[needle.length()];
getNext(next, needle);
for(int i = 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(j == needle.length()){
return i - needle.length() + 1;
}
}
return -1;
}
public void getNext(int[] next, String needle){
int j = 0;
next[0] = 0;
for(int i = 1; i < needle.length(); i++){
while(j > 0 && needle.charAt(i) != needle.charAt(j)){
j = next[j-1];
}
if(needle.charAt(i) == needle.charAt(j)){
j++;
}
next[i] = j;
}
}
}
LeetCode 459.重复的子字符串
文章讲解:代码随想录
视频讲解:字符串这么玩,可有点难度! | LeetCode:459.重复的子字符串_哔哩哔哩_bilibili
力扣题目: LeetCode 459.重复的子字符串
思路:
1.在由重复字符串构成的字符串中,该字符串长度-该字符串的最长前后缀长度=最小重复字串。
2.如果该字符串长度%(该字符串长度-该字符串的最长前后缀长度)= 0,就证明该这字符串存在重复字串。
代码如下(Java):
class Solution {
public boolean repeatedSubstringPattern(String s) {
if(s.equals("")) return false;
int[] next = new int[s.length()];
int len = s.length();
for(int i = 1, j = 0; i < len; 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;
}
if(next[len-1] > 0 && len % (len - next[len-1]) == 0){
return true;
}
return false;
}
}
双指针总结文章:代码随想录
字符串总结文章:代码随想录