【字符串匹配】【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;
    }
}
相关推荐
weixin_4723394622 分钟前
Maven 下载安装与配置教程
java·maven
phoenix@Capricornus1 小时前
反向传播算法——矩阵形式递推公式——ReLU传递函数
算法·机器学习·矩阵
Magnum Lehar1 小时前
3d游戏引擎EngineTest的系统实现3
java·开发语言·游戏引擎
Inverse1621 小时前
C语言_动态内存管理
c语言·数据结构·算法
数据与人工智能律师1 小时前
虚拟主播肖像权保护,数字时代的法律博弈
大数据·网络·人工智能·算法·区块链
就叫飞六吧2 小时前
Spring Security 集成指南:避免 CORS 跨域问题
java·后端·spring
Mcworld8572 小时前
java集合
java·开发语言·windows
天黑请闭眼2 小时前
IDEA:程序编译报错:java: Compilation failed: internal java compiler error
java·intellij-idea
wuqingshun3141592 小时前
蓝桥杯 16. 外卖店优先级
c++·算法·职场和发展·蓝桥杯·深度优先
YouQian7723 小时前
2025春训第十九场
算法