@[TOC](代码随想录算法训练营第九天 | LeetCode 28. 实现 strStr() 459.重复的子字符串)
一、 LeetCode 28. 实现 strStr()
1. 题目链接
2. 学习资料:
3. 思路
- 构建KMP算法的next数组(前缀表-> 前缀表要求的就是相同前后缀的长度)
- 初始化
- 处理前后缀不相同的情况
- 处理前后缀相同的情况
- 更新next数组的值
void getNext(int* next, const string& s){
//1.初始化
int j = 0;
next[0] = 0;
for(int i = 1; i < s.size(); i++) { // 注意i从1开始
//2.处理前后缀不相同的情况
while (j > 0 && s[i] != s[j] ) { // j要保证大于0,因为下面有取j-1作为数组下标的操作,前后缀不相同了
j = next[j-1]; // 注意这里,是要找前一位的对应的回退位置了
}
//3.处理前后缀相同的情况
if (s[i] == s[j]) { // 找到相同的前后缀
j++;
}
//4.更新next数组的值
next[i] = j; // 将j(前缀的长度)赋给next[i]
}
}
- 将needle这个模式字符串放入getNext函数中,获得这个字符串的前缀表
- 声明一个变量 j 指向模式串起始位置,i指向文本串起始位置。
- 如果j所指向的元素无法和文本串中的元素相匹配,那么我们让j 的值等于前缀表中j所在位置的前一个位置中存储的值
- 如果j所指向的元素和文本串中的元素相匹配,让j++
- 判断 j 的值是否是模式串的大小,如果是的话返回 i - needl.length()+1;<- 这就是文本串中出现模式串的起始位置。
4. 代码
class Solution {
public int strStr(String haystack, String needle) {
if( needle.length() == 0){
return 0;
}
int[] next = new int[needle.length()];
getNext(next,needle);
int j = 0;
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 s){
int j =0;
next[0] =0;
for(int 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;
}
}
}
今日收获
KMP算法的应用场景是什么?
KMP算法用在,给我们一个字符串,让我们判断另一个字符串是否在这个字符串中出现过这种问题。
二、 LeetCode 459.重复的子字符串
1. 题目链接
2. 学习资料:
3. 思路
4. 代码
class Solution {
public boolean repeatedSubstringPattern(String s) {
if(s.equals("")){
return false;
}
int len = s.length();
//获取前缀表
//1. 初始化
char[] ch = s.toCharArray();
int[] next = new int[len];
next[0] = 0;
for(int i=1,j=0 ; i<len;i++){
//2.处理不匹配的情况
while(j> 0 && ch[i] != ch[j]){
j = next[j-1];
}
//2.处理匹配的情况
if(ch[i] == ch[j]){
j++;
}
//3. 给next数组赋值
next[i] = j;
}
if(next[len-1] != 0 && len % (len - next[len-1]) == 0){
return true;
}
return false;
}
}