字符串——28. 实现 strStr()

简介: 本专栏按照数组—链表—哈希—字符串—栈与队列—二叉树—回溯—贪心—动态规划—单调栈的顺序刷题,采用代码随想录所给的刷题顺序,一个正确的刷题顺序对算法学习是非常重要的,希望对大家有帮助

1 题目描述

  1. 实现 strStr()

实现 strStr() 函数。

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

说明:

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

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

2 题目示例

示例 1:
输入:haystack = "hello", needle = "ll"
输出:2

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

3 题目提示

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

4 思路

本题是经典的字符串单模匹配的模型,因此可以使用字符串匹配算法解决,常见的字符串匹配算法包括暴力匹配、Knuth-Morris-Pratt算法、Boyer-Moore算法、Sunday 算法等,本文将讲解Knuth-Morris-Pratt算法。
因为哈希方法可能出现哈希值相等但是字符串不相等的情况,而strStr函数要求匹配结果必定正确,因此本文不介绍哈希方法,有兴趣的读者可以自行了解滚动哈希的实现(如Rabin-Karp算法)。
方法一:暴力匹配思路及算法
我们可以让字符串needle 与字符串haystack的所有长度为m的子串均匹配一次。
为了减少不必要的匹配,我们每次匹配失败即立刻停止当前子串的匹配,对下一个子串继续匹配。如果当前子串匹配成功,我们返回当前子串的开始位置即可。如果所有子串都匹配失败,则返回—1。
复杂度分析
时间复杂度:o(n x m),其中n是字符串hagystack的长度,m是字符串needle的长度。最坏情况下我们需要将字符串needle与字符串haystack的所有长度为m的子串均匹配一次。
空间复杂度:O(1)。我们只需要常数的空间保存若干变量。
方法二:KMP
介绍不说了,太长,大家可以自己搜索一下

5 我的答案

方法一:暴力

class Solution {
    public int strStr(String haystack, String needle) {
        int n = haystack.length(), m = needle.length();
        for (int i = 0; i + m <= n; i++) {
            boolean flag = true;
            for (int j = 0; j < m; j++) {
                if (haystack.charAt(i + j) != needle.charAt(j)) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                return i;
            }
        }
        return -1;
    }
}

方法二:KMP

class Solution {
    public int strStr(String haystack, String needle) {
        int n = haystack.length(), m = needle.length();
        if (m == 0) {
            return 0;
        }
        int[] pi = new int[m];
        for (int i = 1, j = 0; i < m; i++) {
            while (j > 0 && needle.charAt(i) != needle.charAt(j)) {
                j = pi[j - 1];
            }
            if (needle.charAt(i) == needle.charAt(j)) {
                j++;
            }
            pi[i] = j;
        }
        for (int i = 0, j = 0; i < n; i++) {
            while (j > 0 && haystack.charAt(i) != needle.charAt(j)) {
                j = pi[j - 1];
            }
            if (haystack.charAt(i) == needle.charAt(j)) {
                j++;
            }
            if (j == m) {
                return i - m + 1;
            }
        }
        return -1;
    }
}
相关文章
|
7月前
|
存储 C语言
【我爱C语言】详解字符函数isdigit和字符串转换函数(atoi和snprintf实现互相转换字符串)&&三种strlen模拟实现2
【我爱C语言】详解字符函数isdigit和字符串转换函数(atoi和snprintf实现互相转换字符串)&&三种strlen模拟实现
|
7月前
|
C语言
字符串函数`strlen`、`strcpy`、`strcmp`、`strstr`、`strcat`的使用以及模拟实现
字符串函数`strlen`、`strcpy`、`strcmp`、`strstr`、`strcat`的使用以及模拟实现
110 1
|
2月前
解析与模拟常用字符串函数strcpy,strcat,strcmp,strstr(一)
解析与模拟常用字符串函数strcpy,strcat,strcmp,strstr(一)
33 0
|
2月前
|
存储 C语言 数据格式
解析spritf和sscanf与模拟常用字符串函数strchr,strtok(二)
解析spritf和sscanf与模拟常用字符串函数strchr,strtok(二)
20 0
|
7月前
|
Java 编译器 C语言
深入了解字符(串)函数 -- -- 字符(串)函数的实现(strlen、strcpy、strcmp、strcat、strstr、)内存函数的实现(memcpy、memmove)
深入了解字符(串)函数 -- -- 字符(串)函数的实现(strlen、strcpy、strcmp、strcat、strstr、)内存函数的实现(memcpy、memmove)
47 0
|
7月前
|
C语言
深入理解字符串函数和字符函数(islower和isupper、tolower和toupper、strlen、strcpy、strcat、strcmp)(一)
深入理解字符串函数和字符函数(islower和isupper、tolower和toupper、strlen、strcpy、strcat、strcmp)(一)
|
7月前
|
C语言
深入理解字符串函数(strstr、strtok、strerror)(二)
深入理解字符串函数(strstr、strtok、strerror)(二)
字符串函数strncmp
字符串函数strncmp
123 1
字符串函数__strstr
str1和str2字符串中一定要有'\0',不然不能正确从字符串查到子串
字符串函数__strlen()
strlen()计算的是字符串的长度的,引用的头文件是#include<string.h>