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. CodeGen字段循环Field Loop

    CodeGen字段循环Field Loop 字段循环是一个模板文件构造,它允许迭代CodeGen拥有的有关字段的集合.这些字段定义可以来自以下两个位置之一: •如果基于从存储库结构中获取的信息生成代码 ...

  2. mysql 高级和 索引优化,目的:查的好,查的快,性能好

    1-事物隔离级别: 更新丢失, 并发情况下,对同一字段进行更新,就会出现更新丢失,采用乐观锁,比较版本号或时间戳可解决 读未提交 解决了更新丢失但是会引起脏读, 二个session.sessionA中 ...

  3. 面试官就是要问我SpringMVC的源码,差点顶不住!

    <对线面试官>系列目前已经连载22篇啦!有深度风趣的系列! [对线面试官]Java注解 [对线面试官]Java泛型 [对线面试官] Java NIO [对线面试官]Java反射 & ...

  4. 狂神说redis笔记(一)

    一.Nosql概述 1.单机Mysql时代 90年代,一个网站的访问量一般不会太大,单个数据库完全够用.随着用户增多,网站出现以下问题: 数据量增加到一定程度,单机数据库就放不下了 数据的索引(B+ ...

  5. 【NX二次开发】Block UI 切换开关

    属性说明 常规         类型 描述     BlockID     String 控件ID     Enable     Logical 是否可操作     Group     Logical ...

  6. 【NX二次开发】Block UI 截面构建器

    属性说明 属性   类型   描述   常规           BlockID    String    控件ID    Enable    Logical    是否可操作    Group    ...

  7. Siamese network总结

    ​前言: 本文介绍了Siamese (连体)网络的主要特点.训练和测试Siamese网络的步骤.Siamese网络的应用场合.Siamese网络的优缺点.为什么Siamese被称为One-shot分类 ...

  8. 重新点亮linux 命令树————帮助命令[一]

    前言 重新整理一下linux的命令. 正文 这里首先介绍帮助命令. 帮助命令常用的有三个: man help info 那么就来看下这三个. man 第一个man,man不是男人的意思,而是manua ...

  9. 乘风破浪,Java遇见OpenJDK GA(Build By Microsoft),即将晋升为Azure云管理服务默认JVM

    什么是Microsoft Build of OpenJDK Java Development Kit (JDK) 是Sun公司(已被Oracle收购)针对Java开发员的软件开发工具包.自从Java推 ...

  10. liunx驱动之字符设备的注册

    上一篇文章学习了如何编写linux驱动,通过能否正常加载模块进行验证是否成功,有做过liunx应用开发的小伙伴都知道驱动会在'/dev'目录下以文件的形式展现出来,所以只是能加载驱动模块不能算是完成驱 ...