【LeetCode】28. 实现 strStr()

28. 实现 strStr()

知识点:字符串;KMP算法

题目描述

实现 strStr() 函数。

给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回  -1 。

说明
当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与 C 语言的 strstr() 以及 Java 的 indexOf() 定义相符。

示例
输入:haystack = "hello", needle = "ll" 输出:2 输入:haystack = "aaaaa", needle = "bba" 输出:-1 输入:haystack = "", needle = "" 输出:0

解法一:暴力法

直接对于haystack中的每一位,依次比较needle,如果发生不匹配了,则移动到haystack中的下一位;

class Solution { public int strStr(String haystack, String needle) { if(needle.length() == 0) return 0; for(int i = 0; i <= haystack.length()-needle.length(); i++){ //注意判断条件; int j = 0; while(j < needle.length() && haystack.charAt(i+j) == needle.charAt(j)){ j++; } if(j == needle.length()) return i; //满足证明完全匹配上了; } return -1; } }

时间复杂度:O(NM);

解法二:KMP算法

可以查看KMP算法
KMP算法的本质上就是在利用先前的信息减少不可能的匹配,把不可能的匹配都直接过滤。而这个过滤的依据就是next数组,next数组里的数的含义是以此数结尾时,最多能用前面几个数来顶替掉我们后面几个数。
要清楚我们根据next数组去过滤是不可能漏掉情况的。为什么呢?比如说ababca,我到了最后一个a处匹配不上了,那按照上面的解法,现在应该看a处前一位也就是c的对应next值,很明显next[4]是0,所以模式串的指针就移动到最开始,也就等于将模式串的首位直接对齐到了主串中原本与a不匹配的那个位置,中间可能错过某些可能吗?比如说我最开始的ab可以移动到2,3位置处,那也是ab说不定可能呢,其实这是不可能的,为什么呢,反证法;如果0和1处的ab匹配上了2和3处的ab,那么后一个一定不匹配,因为如果匹配的话,那就是说前3个能匹配上后3个,那next[4]就等于3而不是0了,所以这也就说明了为什么我们是看前一个也就是看c的next值,因为无论怎样,我们都是要经过它的,如果不看它,那它前面几个匹配上了,到它也匹配不上;

class Solution { public int strStr(String haystack, String needle) { if(needle.length() == 0) return 0; if(haystack.length() == 0) return -1; char[] s = haystack.toCharArray(); char[] p = needle.toCharArray(); return KMP(s,p); } private int KMP(char[] s, char[] p){ int tar = 0; //主串中待匹配的位置; int pos = 0; //模式串中待匹配的位置; int m = s.length; int n = p.length; int[] next = next(p, n); //构建next数组; while(tar < m){ if(s[tar] == p[pos]){ //匹配上就接着比下一个; tar++; pos++; }else if(pos != 0){ //匹配不上了,而且pos指针还没移动到模式串最开始; pos = next[pos-1]; //看匹配不上的前一位的next数组值; }else{ //pos已经到模式串最开始了,而且会经过最开始的if,如果这也没匹配上,说明tar对应的值匹配不上,直接向后移一位; tar++; } if(pos == n){ //pos到了模式串最后,全匹配上了; return tar-n; } } return -1; } private int[] next(char[] p, int n){ int[] next = new int[n]; int now = 0; int i = 1; while(i < n){ if(p[now] == p[i]){ now++; next[i] = now; i++; }else if(now != 0){ //now没回到最开始呢; now = next[now-1]; //使得A的K前缀等于B的K后缀的最大K;A和B又一样。所以就看A就可以了; //看now前一位的最长前后缀; }else{ next[i] = now; //移动到最开始了还不行,那就是0了; i++; } } return next; } }

时间复杂度:O(N)+O(M);

体会

要掌握字符串匹配,要掌握KMP算法,要经常看这篇文章:KMP算法


__EOF__

本文作者Curryxin
本文链接https://www.cnblogs.com/Curryxin/p/15047089.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Curryxin  阅读(129)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
Live2D
欢迎阅读『【LeetCode】28. 实现 strStr()』
点击右上角即可分享
微信分享提示