【字符串匹配】【KMP算法】Leetcode 28 找出字符串中第一个匹配项的下标☆

【字符串匹配】【KMP算法】Leetcode 28 找出字符串中第一个匹配项的下标

---------------🎈🎈题目链接🎈🎈-------------------


🔴任务:要在文本串:aabaabaafa 中查找是否出现过一个模式串:aabaaf

(1)前缀和后缀

前缀是指不包含最后一个字符的,所有以第一个字符开头的连续子串。

比如aabaaf的前缀包括:a,aa,aab,aaba,aabaa

后缀是指不包含第一个字符的,所有以最后一个字符结尾的连续子串。

比如aabaaf的后缀包括:f,af,aaf,baaf,abaaf

(2)前缀表(最长相同的前缀和后缀的长度)

前缀表(最长相同的前缀和后缀的长度)

前缀表(最长相同的前缀和后缀的长度)

前缀表(最长相同的前缀和后缀的长度)

作用:记录下标i之前(包括i)的字符串中,有多大长度的相同前缀后缀

模式串aabaaf的前缀表:

字符串 最长相等前后缀
a 0
aa 1
aab 0
aaba 1
aabaa 2
aabaaf 0

前缀表的任务 :当前位置匹配失败,找到之前已经匹配上的位置,再重新匹配。

也意味着在某个字符失配时,前缀表会告诉你下一步匹配中,模式串应该跳到哪个位置。

文本串 a a b a a b a a f
模式串下标 0 1 2 3 4 5
模式串 a a b a a f
--前缀表-- 0 1 0 1 2 0

当匹配到 b 的时候,模式串为 f ,匹配失败。

于是寻找 f 前面的字符串 aabaa, 他的最长相等前缀和后缀字符串是 aa , 因为找到了最长相等的前缀和后缀,匹配失败的位置是后缀子串的后面,那么我们找到与其相同的前缀的后面(即前缀表中发现冲突位置的前面的字符串------aabaa对应的前缀表为【2】,因此找到模式串中下标索引为【2】的位置 ------ b 的位置开始)重新匹配就可以了。

文本串 a a b a a b a a f
模式串 a a b a a f

(3)匹配过程示意

(4)next数组的实现方法

next数组详解视频!
代码随想录文字版
!!!!!代码随想录视频版本!!!!!

1.初始化

【i:后缀的末尾】初始化为1,

【j:前缀的末尾】初始化为0 , next [ 0 ] = 0
j:也代表了i包括i之前的字符串的最长相等前后缀长度

2.处理前后缀不相等的情况 :

复制代码
j连续回退 ------------ j=next [ j-1 ], (在j大于0的情况下)

3.处理前后缀相同的情况:

复制代码
j++  →  更新next数组:next [ i ] = j   →    i++

4.求next数组的程序:

java 复制代码
1.初始化 【i:后缀的末尾】初始化为1,  【j:前缀的末尾,也代表i包括i前字符的最长相等前后缀长度】初始化为0 ,   next[0] = 0
2.处理前后缀不相等的情况
3.处理前后缀相同的情况

 //求前缀表next
    private void getNext(int[] next, String s){
        int j = 0;  // 初始化j为前缀末尾0,i为后缀的末尾
        next[0] = 0;
        for(int i = 1; i < s.length(); i++){ 
            while(j > 0 && s.charAt(j) != s.charAt(i)){ 
                j = next[j-1];
            }
            if(s.charAt(j) == s.charAt(i)){ // 如果相同,前缀末尾j++
                j++;
            }
            next[i] = j;  // 将前缀的长度给next[i]
        }
    } 

题目做法

解法1 KMP算法

时间复杂度O(N)

空间复杂度O(N)

java 复制代码
  class Solution {
    public int strStr(String haystack, String needle) {
        if(haystack.length() < needle.length()) return -1;

        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
    private void getNext(int[] next, String s){
        int j = 0;  // 初始化j为前缀末尾0,i为后缀的末尾
        next[0] = 0;
        for(int i = 1; i < s.length(); i++){ 
            while(j > 0 && s.charAt(j) != s.charAt(i)){ 
                j = next[j-1];
            }
            if(s.charAt(j) == s.charAt(i)){ // 如果相同,前缀末尾j++
                j++;
            }
            next[i] = j;  // 将前缀的长度给next[i]
        }
    } 
}

解法2 暴力做法

从大字符串的第一个元素开始,比对小字符串,一旦出现不一样的就从大字符串的下一个元素开始进行比对

如果小字符串遍历结束时都一样,则return对应的下标

如果大字符串遍历完小字符串还没遍历完,return-1

遍历完大字符串前都找不到的话就return -1

时间复杂度O(N^2)

空间复杂度O(N)

java 复制代码
class Solution {
    public int strStr(String haystack, String needle) {
        // 暴力做法
        char[] ch1 = haystack.toCharArray();
        char[] ch2 = needle.toCharArray();
        int result = -1;
        for(int i = 0; i < ch1.length; i++){ // haystack的遍历
            if(ch1[i] == ch2[0]){
                int outside = i;
                int inside = 0;
                while(ch1[outside] == ch2[inside]){
                    outside++;
                    inside++;
                    if(inside == ch2.length){return outside-ch2.length;}
                    else if(outside == ch1.length){return result;}
                }
            }
        }
        return result;
    }
}
相关推荐
布朗克16844 分钟前
Java 10 新特性及具体应用
java·开发语言·新特性·java10
code小毛孩1 小时前
leetcode hot100数组:缺失的第一个正数
数据结构·算法·leetcode
ZZHow10244 小时前
JavaWeb开发_Day05
java·笔记·web
CHEN5_024 小时前
【Java虚拟机】垃圾回收机制
java·开发语言·jvm
Warren984 小时前
Lua 脚本在 Redis 中的应用
java·前端·网络·vue.js·redis·junit·lua
legendary_bruce7 小时前
【22-决策树】
算法·决策树·机器学习
独行soc7 小时前
2025年渗透测试面试题总结-18(题目+回答)
android·python·科技·面试·职场和发展·渗透测试
艾伦~耶格尔8 小时前
【数据结构进阶】
java·开发语言·数据结构·学习·面试
爪洼传承人8 小时前
18- 网络编程
java·网络编程
max5006008 小时前
基于桥梁三维模型的无人机检测路径规划系统设计与实现
前端·javascript·python·算法·无人机·easyui