Leetcode的AC指南 —— 字符串/KMP:28.找出字符串中第一个匹配项的下标

这篇具有很好参考价值的文章主要介绍了Leetcode的AC指南 —— 字符串/KMP:28.找出字符串中第一个匹配项的下标。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

摘要:
Leetcode的AC指南 —— 字符串/KMP:28.找出字符串中第一个匹配项的下标。题目介绍:给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。

一、题目


题目介绍:给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。

力扣题目链接

示例 1:

输入:haystack = "sadbutsad", needle = "sad"
输出:0
解释:"sad" 在下标 06 处匹配。
第一个匹配项的下标是 0 ,所以返回 0

示例 2:

输入:haystack = "leetcode", needle = "leeto"
输出:-1
解释:"leeto" 没有在 "leetcode" 中出现,所以返回 -1

提示:
1 <= haystack.length, needle.length <= 104
haystack 和 needle 仅由小写英文字符组成

二、解析(go)


1、一个简单的AC方法

思路:让needle在haystack中滑动

go:

func strStr(haystack string, needle string) int {

	runes := []byte(haystack)

	for i := 0; i <= len(haystack)-len(needle); i++ {
		if string(runes[i:len(needle)+i]) == needle {
			return i
		}
	}

	return -1

}

  • 时间复杂度O(n-m)
  • 空间复杂度O(n)

2、KMP算法:直接使用前缀表作为next数组

思路:

  • 构造next数组

    1. 初始化:前缀末尾指针before指向第一个字符,第一个子串的前后缀长度next[0]为0
    2. 默认before指针之前的字符与behind指针之前的字符相等。
    3. 比较before指向的字符与behind指向的字符是否相等。
      • 当不相同时,before指向前一个字符,重新比较,直到before指向第一个字符或者before与behind的字符相等时,结束比较。
      • 当又相同时,before指向下一个字符。
    4. before的位置就是最长前后缀长度,更新next数组。
  • 使用next数组做匹配文章来源地址https://www.toymoban.com/news/detail-782994.html

    • 初始化
      • i为文本串起始位置,j为模式串起始位置
      • 得到next数组
    • 在文本串中查找模式串,对比i和j分别对应的字符
      • 若i和j相等,则i和j同时后移
      • 若i和j不相等,则j寻找之前匹配的位置,
        • 也就是通过next数组的最大相同子串长度滑动j,确定从模式串的哪个位置开始重新比较
      • 当 j 比完模式串的最后一个字符后,说明模式串在文本串中出现过,返回结果
      • 若文本串遍历结束,j也没有指向模式串的最后一个字符,就返回-1
//直接将前缀表作为next数组
func getnext(next []int, s string) {
    // before: 前缀末尾,前缀长度
    // behand:后缀末尾
    
    before := 0
    next[0] = 0
    for behind := 1; behind < len(s); behind++ {
        for before > 0 && s[behind] != s[before] { // 前缀与后缀不相等
            before = next[befor-1]
        }
        if s[behind] == s[before] { // 前缀与后缀相等
            before++
        }
        next[behind] = before
    }
}
// 直接将前缀表作为next数组的匹配实现
func strStr(haystack string, needle string) int {
    j := 0 // j 为模式串的起始位置, next数组记录的起始位置为0
    next := make([]int, len(needle))
    getnext(next, needle)
    for i := 0; i < len(haystack); i++ { // i从0开始
       for j > 0 && haystack[i] != needle[j] { // 不匹配
          j = next[j-1] // j寻找之前匹配的位置
       }
       if haystack[i] == needle[j] { // 匹配,j 和 i同时向后移动
          j++ // i的增加在for循环中
       }
       if j == len(needle) { // 文本串haystack中出现了模式串needle
          return i - j + 1
       }
    }
    return -1
}

  • n为文本串长度,m为模式串长度。
  • 匹配的过程是O(n),
  • 单独生成next数组,时间复杂度是O(m)。
  • 整个KMP算法的时间复杂度是O(n+m)的。

三、其他语言版本


Java

class Solution {
    //前缀表(不减一)Java实现
    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;

    }
    
    private void getNext(int[] next, String s) {
        int j = 0;
        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++;
            next[i] = j; 
        }
    }
}

C++

class Solution {
public:
    void getNext(int* next, const string& s) {
        int j = 0;
        next[0] = 0;
        for(int i = 1; i < s.size(); i++) {
            while (j > 0 && s[i] != s[j]) {
                j = next[j - 1];
            }
            if (s[i] == s[j]) {
                j++;
            }
            next[i] = j;
        }
    }
    int strStr(string haystack, string needle) {
        if (needle.size() == 0) {
            return 0;
        }
        int next[needle.size()];
        getNext(next, needle);
        int j = 0;
        for (int i = 0; i < haystack.size(); i++) {
            while(j > 0 && haystack[i] != needle[j]) {
                j = next[j - 1];
            }
            if (haystack[i] == needle[j]) {
                j++;
            }
            if (j == needle.size() ) {
                return (i - needle.size() + 1);
            }
        }
        return -1;
    }
};

Python


class Solution:
    def getNext(self, next: List[int], s: str) -> None:
        j = 0
        next[0] = 0
        for i in range(1, len(s)):
            while j > 0 and s[i] != s[j]:
                j = next[j - 1]
            if s[i] == s[j]:
                j += 1
            next[i] = j
    
    def strStr(self, haystack: str, needle: str) -> int:
        if len(needle) == 0:
            return 0
        next = [0] * len(needle)
        self.getNext(next, needle)
        j = 0
        for i in range(len(haystack)):
            while j > 0 and haystack[i] != needle[j]:
                j = next[j - 1]
            if haystack[i] == needle[j]:
                j += 1
            if j == len(needle):
                return i - len(needle) + 1
        return -1

到了这里,关于Leetcode的AC指南 —— 字符串/KMP:28.找出字符串中第一个匹配项的下标的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 力扣-28. 找出字符串中第一个匹配项的下标

    力扣题目 给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。 示例 1: 输入:haystack = “sadbutsad”, needle = “sad” 输出:0 解释:“sad” 在下标 0 和 6 处匹配。 第

    2024年02月20日
    浏览(29)
  • LeetCode:459. 重复的子字符串 —【2、KMP算法】

    🍎道阻且长,行则将至。🍓 🌻算法,不如说它是一种思考方式🍀 算法专栏: 👉🏻123 题目描述 :给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。 来源:力扣(LeetCode) 难度: 简单 提示: 1 = s.length = 104 s 由小写英文字母组成 示例 1: 输入:

    2024年02月04日
    浏览(39)
  • 【leetcode 力扣刷题】字符串匹配之经典的KMP!!!

    以下是能用KMP求解的算法题,KMP是用于字符串匹配的经典算法【至今没学懂………啊啊啊】 题目链接:28. 找出字符串中第一个匹配项的下标 题目内容: 题意还是很好理解的,要在字符串haystack中查找一个完整的needle,即字符串匹配。 暴力求解就是用 两层循环 :haystack从第

    2024年02月09日
    浏览(28)
  • 代码随想录 Leetcode459. 重复的子字符串(KMP算法)

            此解法读者需要了解什么是KMP算法以及KMP算法中next数组的具体含义才能理解         因为在KMP算法的next数组中,next[index]表示 i ndex之前的最大长度的相同前缀后缀值 ,那么要判断整个字符串中是否由重复字串构成,只需要以下两个条件:         1.next[n - 1] !=

    2024年01月19日
    浏览(49)
  • 【算法|动态规划No.28】leetcode1312. 让字符串成为回文串的最少插入次数

    个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 🍔本专栏旨在提高自己算法能力的同时,记录一下自己的学习过程,希望对大家有所帮助 🍓希望我们一起努力、成长,共同进步。

    2024年02月06日
    浏览(42)
  • 【kmp算法】字符串匹配

    kmp算法解决的是字符串匹配的问题,具体来说假定我们要在主串s[ ] 中匹配模式串p[ ],找到匹配到的位置loc; 最自然的想法是暴力写法 (BF)枚举主串字符s[ i ] ,和模式串p[ j ]。一个一个匹配,如果匹配失败,i指针回退回起点,往前进一位,再次进行比较,知道匹配成功。

    2024年02月04日
    浏览(47)
  • 字符串匹配-KMP算法

    KMP算法,字符串匹配算法,给定一个主串S,和一个字串T,返回字串T与之S匹配的数组下标。 在学KMP算法之前,对于两个字符串,主串S,和字串T,我们根据暴力匹配,定义两个指针,i指向主串S的起始,j指向字串T的起始,依次比较,如果 主串i位置的值等于子串j位置的值,

    2024年02月14日
    浏览(36)
  • 字符串匹配算法:KMP

    Knuth–Morris–Pratt(KMP)是由三位数学家克努斯、莫里斯、普拉特同时发现,所有人们用三个人的名字来称呼这种算法,KMP是一种改进的字符串匹配算法,它的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。它的时间复杂度是 O(m+n) 字

    2024年02月06日
    浏览(47)
  • KMP-重复子字符串

    Problem: 459. 重复的子字符串 给定一个字符串str1, 判断其是否由重复的子串构成。 例子1:输入 str1=‘ababab’ ;输出 true 例子2:输入 str1=‘ababac’ ;输出 false 重复子字符串组成的字符串,其肯定存在一个后缀和前缀是一样的,并且这个后缀其由后缀前面的字符子串组成。所以

    2024年01月25日
    浏览(31)
  • ACM - 字符串 - 基础(KMP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1711 题目大意 找出子串第一次出现的位置,找不到输出 - 1. next 数组的含义: next [ i ] 表示 :以 i 为终点,以 1 为起点,前后缀能一致的最长字串。 (在某些头文件有命名过next,所以代码里面以 ne 代表next) next [ i ] = x 表示:如果

    2024年02月04日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包