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算法

【LeetCode】28. 实现 strStr()的更多相关文章

  1. <每日 1 OJ> -LeetCode 28. 实现 strStr()

    题目: 实现 strStr() 函数. 给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始).如果不存 ...

  2. 前端与算法 leetcode 28.实现 strStr()

    # 前端与算法 leetcode 28.实现 strStr() 题目描述 28.移除元素 概要 这道题的意义是实现一个api,不是调api,尽管很多时候api的速度比我们写的快(今天这个我们可以做到和 ...

  3. Java实现 LeetCode 28 实现strStr()

    28. 实现 strStr() 实现 strStr() 函数. 给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 ...

  4. 44. leetcode 28. Implement strStr()

    28. Implement strStr() Implement strStr(). Returns the index of the first occurrence of needle in ha ...

  5. [LeetCode] 28. Implement strStr() 实现strStr()函数

    Implement strStr(). Return the index of the first occurrence of needle in haystack, or -1 if needle ...

  6. LeetCode 28 Implement strStr() (实现找子串函数)

    题目链接: https://leetcode.com/problems/implement-strstr/?tab=Description   Problem : 实现找子串的操作:如果没有找到则返回 ...

  7. Leetcode #28. Implement strStr()

    Brute Force算法,时间复杂度 O(mn) def strStr(haystack, needle): m = len(haystack) n = len(needle) if n == 0: ...

  8. Java [leetcode 28]Implement strStr()

    题目描述: Implement strStr(). Returns the index of the first occurrence of needle in haystack, or -1 if ...

  9. [LeetCode] 28. Implement strStr() 解题思路

    Implement strStr(). Returns the index of the first occurrence of needle in haystack, or -1 if needle ...

  10. Leetcode 28——Implement strStr()

    Implement strStr(). Return the index of the first occurrence of needle in haystack, or -1 if needle ...

随机推荐

  1. OFRecord 数据集加载

    OFRecord 数据集加载 在数据输入一文中知道了使用 DataLoader 及相关算子加载数据,往往效率更高,并且学习了如何使用 DataLoader 及相关算子. 在 OFrecord 数据格式 ...

  2. Numba实时变量分析

    Numba实时变量分析 Numba使用引用计数进行垃圾回收,这是一种需要编译器配合的技术.Numba IR对必须插入decref的位置进行编码.这些位置通过实时变量分析确定.相应的源代码是https: ...

  3. Centos 安装 Influxdb + Chronograf

    安装 Influxdb  1:下载安装包 官网下载地址 https://portal.influxdata.com/downloads/# wget https://dl.influxdata.com ...

  4. NX二次开发-克隆操作

    模板文件: 克隆替换字符串: 1 #include "Text.h" 2 extern DllExport void ufsta(char *param, int *returnC ...

  5. 【NX二次开发】获取对象边界包容盒的三个函数UF_MODL_ask_bounding_box

    今天看到胡工对bounding_box的分享,我也来测试一番(原帖地址:https://www.ugapi.com/thread-10287.html) 获取对象的边界盒子的三个函数: 1 UF_MO ...

  6. spring boot 并发请求,其他系统接口,丢失request的header信息【多线程、线程池、@Async 】

    场景:一次迭代在灰度环境发版时,测试反馈说我开发的那个功能,查询接口有部分字段数据是空的,后续排查日志,发现日志如下: feign.RetryableException: cannot retry d ...

  7. 天天写order by,你知道Mysql底层如何执行吗?

    在实际的开发中一定会碰到根据某个字段进行排序后来显示结果的需求,但是你真的理解order by在 Mysql 底层是如何执行的吗? 假设你要查询城市是苏州的所有人名字,并且按照姓名进行排序返回前 10 ...

  8. 解Bug之路-ZooKeeper集群拒绝服务

    解Bug之路-ZooKeeper集群拒绝服务 前言 ZooKeeper作为dubbo的注册中心,可谓是重中之重,线上ZK的任何风吹草动都会牵动心弦.最近笔者就碰到线上ZK Leader宕机后,选主无法 ...

  9. ffmpeg实战-音视频基础概念

    转发自白狼栈:查看原文 关于音视频,相信大家都看过电影(视频),听过音乐(音频),至少应该都知道mp4是视频文件,mp3是音频文件. 对于一个音视频文件,都有哪些属性呢?以视频为例,我们可以通过 ff ...

  10. NOIP模拟测试29「爬山·学数数·七十和十七」

    爬山题解不想写了 学数数 离散化然后找到以每一个值为最大值的连续子段有多少个,然后开个桶维护 那么怎么找以每一个值为最大值的连续子段个数 方法1(我的极笨的方法) 考试时我的丑陋思路, 定义极左值为左 ...