当前位置: 首页 > article >正文

【LeetCode】28. 找出字符串中第一个匹配项的下标 【字符串单模匹配:KMP算法】

题目链接

在这里插入图片描述

在这里插入图片描述

Python3

直觉解法

class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
        pn, ph = 0, 0
        n = len(needle) 
        h = len(haystack)
        while ph < h:
            if haystack[ph] == needle[pn]:
                if pn == n-1: # 1234   123
                    return ph - len(needle) + 1
                else: 
                    pn += 1
                    ph += 1
            else: ## 1234  122
                ph = ph - pn + 1
                pn = 0
        return -1

方法一: 暴力解法 ⟮ O ( n × m ) 、 O ( 1 ) ⟯ \lgroup O(n\times m)、O(1) \rgroup O(n×m)O(1)⟯

class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
        for i in range(0, len(haystack)-len(needle)+1):
            if haystack[i:i+len(needle)] == needle:
                return i 
        return -1

在这里插入图片描述

⭐ 方法二:Knuth-Morris-Pratt 算法 [KMP算法] ⟮ O ( m + n ) 、 O ( m ) ⟯ \lgroup O(m+n)、O(m) \rgroup O(m+n)O(m)⟯ 【空间换时间】

在这里插入图片描述
在这里插入图片描述
从而实现 更快地 跳转

在这里插入图片描述
参考链接1
参考链接2: KMP字符串匹配算法2

官方解法链接

class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
        h = len(haystack)
        n = len(needle)
        
        # 获取 needle 的前缀信息
        lis = [0] * n 
        
        j = 0  # 前后  子串长度
        for i in range(1, n): # 需要前后比较, 1个字符无法比较,因此从 i=1 开始
            while j > 0 and needle[i] != needle[j]: 
                j = lis[j-1] # 和之前 相等的长度一样
            if needle[i] == needle[j]:
                j += 1  

            lis[i] = j 

        # 0  1 2 3 4 5 6
        # a  a b a a a b   needle
        # 0  1 0 1 2 2 3  前缀子串 后缀子串 相同的长度  若是 needle[j] 不匹配了,注意是 lis[j-1] 存储的才是 待比较的下一个 j

        # a  a c a a

        # 根据上述的 信息进行 匹配
        j = 0  # 遍历 needle 下标
        for i in range(0, h): # 遍历 haystack 下标
            while j > 0 and haystack[i] != needle[j]:  #               
                j = lis[j-1]  # 这里 根据 前后缀 信息  快速跳转  
            if haystack[i] == needle[j]:
                j += 1

            if j == n: # needle 已全部匹配 因为前面的if 成立,j多加了1 
                return i - n + 1

        return -1 


在这里插入图片描述
链接

class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
        def get_next():
            for i in range(1, len(needle)):
                k =[i-1]
                while needle[i] != needle[k]:
                    if k == 0:
                        k -= 1
                        break 
                    else:
                        k =[k-1][i] = k+1

        n = len(needle)= [0] * n 
        get_next()   # 生成 needle 的next 数组

        i = 0 
        j = 0 
        while i < len(haystack):
            if haystack[i] == needle[j]:
                i += 1
                j += 1
            elif j == 0:
                i += 1
            else:
                j =[j-1]
            if j >= n:
                return i - n 
        return -1

C++

KMP 算法 ⟮ O ( h + n ) 、 O ( n ) ⟯ \lgroup O(h+n)、O(n) \rgroup O(h+n)O(n)⟯

class Solution {
public:
    int strStr(string haystack, string needle) {
        int h = haystack.size(), n = needle.size();
        vector<int> lis(n);
        for (int i = 1, j = 0; i < n; ++i){
            while (j > 0 && needle[i] != needle[j]){
                j = lis[j-1];
            }
            if (needle[i] == needle[j]){
                ++j;
            }

            lis[i] = j;
        }

        for (int i = 0, j = 0; i < h; ++i){
            while (j > 0 && haystack[i] != needle[j]){
                j = lis[j-1];
            }
            if (haystack[i] == needle[j]){
                ++j;
            }
            if (j == n){
                return i - n + 1;
            }
        }
        return -1;
    }
};

暴力解法

class Solution {
public:
    int strStr(string haystack, string needle) {
        int h = haystack.size(), n = needle.size();
        
        int j = 0, i = 0;
        while (i < h){
            if (haystack[i] == needle[j]){
                if (j == n-1){
                    return i - n + 1;
                }
                else{
                    ++j;
                    ++i;
                }
            }
            else{
                j = 0;
                i = i - j + 1;
            }
        }
        return -1;
    }
};

http://www.kler.cn/news/163131.html

相关文章:

  • Linux设备分类与设备号
  • Django讲课笔记01:初探Django框架
  • 面试宝典之自我介绍
  • 【嵌入式开发 Linux 常用命令系列 4.2 -- .repo 各个目录介绍】
  • 集简云 x 零售企业丨快速集成有赞商城和微盛企微管家,实现私域运营自动化
  • YOLOv8分割训练及分割半自动标注
  • Android MVVM+coroutine+retrofit+flow+hilt
  • LSTM_预测价格问题_keras_代码实操
  • 喜讯:加速度商城系统全系列产品品牌全新升级为Shopfa
  • Java工程找不到javax.xml.bind.annotation包
  • 【flink番外篇】1、flink的23种常用算子介绍及详细示例(3)-window、distinct、join等
  • STM32 map文件详解
  • Kubernetes(K8s 1.27.x) 快速上手+实践,无废话纯享版
  • running小程序重要技术流程文档
  • 【ELK03】ES 索引的Mapping映射详解、数据类型和settings属性设置
  • 算法:常见的链表算法
  • 插入排序——直接插入排序和希尔排序(C语言实现)
  • 如何进行更好的面试回复之缓存函数在项目中的性能优化?
  • Advanced Renamer
  • 利用R语言heatmap.2函数进行聚类并画热图
  • Shell脚本如何使用 for 循环、while 循环、break 跳出循环和 continue 结束本次循环
  • Vue学习笔记-Vue3中的计算属性与监视属性
  • 【数据结构】拆分详解 - 二叉树的链式存储结构
  • 消费升级:无人零售的崛起与优势
  • 【MATLAB源码-第97期】基于matlab的能量谷优化算法(EVO)机器人栅格路径规划,输出做短路径图和适应度曲线。
  • git操作:使用vscode集成
  • Spring Cloud Gateway中对admin端点进行认证
  • 自动补全的 select antd react
  • php+mysql期末作业小项目
  • kafka学习笔记--安装部署、简单操作