代码随想录算法训练营第八天|初见KMP算法以及字符串的总结

目录

LeetCode 28.实现strStr()

LeetCode 459.重复的子字符串


LeetCode 28.实现strStr()

文章讲解:代码随想录

视频讲解:帮你把KMP算法学个通透!(理论篇)_哔哩哔哩_bilibili

帮你把KMP算法学个通透!(求next数组代码篇)_哔哩哔哩_bilibili

力扣题目:LeetCode 28.实现strStr()

 

滑动窗口的思路:

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;
    }
}


双指针总结文章:代码随想录


字符串总结文章:代码随想录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值