代码随想录Day09|实现strStr() 重复的子字符串
1.题目链接:找出字符串中第一个匹配项的下标 - 力扣
题目描述:给你两个字符串 haystack
和 needle
,请你在 haystack
字符串中找出 needle
字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle
不是 haystack
的一部分,则返回 -1
。
示例 1:
输入:haystack = "sadbutsad", needle = "sad"
输出:0
解释:"sad" 在下标 0 和 6 处匹配。
第一个匹配项的下标是 0 ,所以返回 0 。
示例 2:
输入:haystack = "leetcode", needle = "leeto"
输出:-1
解释:"leeto" 没有在 "leetcode" 中出现,所以返回 -1 。
文章讲解/视频讲解:https://programmercarl.com/0028.%E5%AE%9E%E7%8E%B0strStr.html
解题思路:
暴力解法,使用两个for循环,一个个向后进行比较。直到找到对应的字符串,循环结束,仍未找到相应的字符串,则返回-1
下面是代码示例:
class Solution {
public int strStr(String haystack, String needle) {
for(int i=0;i<=haystack.length()-needle.length();i++){
int k=i;
int j=0;
while(j<needle.length()&&haystack.charAt(k)==needle.charAt(j)){
k++;
j++;
}
if(j==needle.length()){
return i;
}
}
return -1;
}
}
KMP算法,相较于暴力解法,KMP算法可以避免重头匹配。当出现字符串不匹配的时候,可以知道前面一部分已经匹配了的内容,这样可以避免从头再去做匹配了。
KMP算法需要我们知道子字符串的next值,求next数组,则是需要自己与自己进行比较,算出next值。很容易得知next数组的第一个数值一定是0,我们可以让i=1,然后j=0,进行比较。字母相同则一起往后++,若字母不相同,j就要等于它前一个字母所对应的next值。循环结束,最后求出子字符串对应的next值。
利用子字符串的next值,以及上面的求解方法,也很容易写出匹配的子字符串。
下面试代码示例:
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&&needle.charAt(j)!=haystack.charAt(i)) j=next[j-1];
if(needle.charAt(j)==haystack.charAt(i)) j++;
if(j==needle.length())
return i-needle.length()+1;
}
return -1;
}
//next数组找到相对应的值
public void getNext(int[] next, String s){
int j=0;
next[0]=0;
for(int i=1;i<s.length();i++){
//字符不匹配的情况,j进行回退
while(j>0&&s.charAt(i)!=s.charAt(j)) j=next[j-1];
if(s.charAt(i)==s.charAt(j)) j++;
next[i]=j;
}
}
}
2.题目链接:重复的子字符串 - 力扣
题目描述:给定一个非空的字符串 s
,检查是否可以通过由它的一个子串重复多次构成。
示例 1:
输入: s = "abab"
输出: true
解释: 可由子串 "ab" 重复两次构成。
示例 2:
输入: s = "aba"
输出: false
示例 3:
输入: s = "abcabcabcabc"
输出: true
解释: 可由子串 "abc" 重复四次构成。 (或子串 "abcabc" 重复两次构成。)
文章讲解/视频讲解:https://programmercarl.com/0459.%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2.html
解题思路
使用移动匹配的方式。当一个字符串s:abcabc,那它一定是由前后相同的字符串组成的。既然有前面有相同的字符串,后面有相同的字符串,那么我们可以ss=s+s组成一个这样字符串,第一个s的后面的子串做前面的字符串,第二个前面的子串做后面的字符串。然后把ss的头和尾去掉,寻找新的字符串能不能够组成新的字符串s,如果可以组成,那么说明这个s就是由重复的子字符串组成的。
下面是代码示例:
class Solution{
public boolean repeatedSubstringPattern(String s) {
String ss=s+s;
return ss.substring(1,ss.length()-1).contains(s);
}
}
总结:
今天写的题目比较少,KMP算法在上一年学习过,但是只记得七七八八,还不太会应用。对于计算next的已经会了,但大概的思路还是不能够很清晰的说出来,还是需要多下点功夫,后续补充在评论区(希望自己不是在给自己画饼)算法还是需要偶尔去回顾和学习。第二题关于使用KMP算法的方法还没有完全掌握,周末没有课的时候还需要多看看。今天又了解了一些String字符串的使用方法,还是需要多学多记。