leetcode | Implement strStr() | 实现字符串查找函数

Implement strStr() : https://leetcode.com/problems/implement-strstr/

Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.

如:haystack = “bcbcda”; needle = “bcd” 则 return 2



解析:字符串查找函数,strstr()函数用来检索子串在字符串中首次出现的位置,其原型为:

char *strstr( char *str, char * substr );

思路一:容易实现,然并卵(时间复杂度不满足要求)

两个指针,i 指向haystack 的起始,j 指向 needle 的起始;首先 i 向后走,直至haystack[i] == needle [j]; 然后 j 往后走,如果haystack[i+j] != needle [j] 跳出,如果能走 m 步,即存在相同,返回i;如果存在不匹配,则haystack 后移后,从needle[0]重新比较

原理就是:拿着 needle 字符串 去 haystack 上逐个比较;每次最多需要对比m次,最多重复n次;

时间复杂度为O(m*n),不能满足leetcode的时间要求

注:在写代码前理清思路,

1. 确定解决问题的算法

2. 确定算法的时空复杂度,考虑能不能优化或询问面试官是否要求时空复杂度。

3. 有哪些特殊情况需要处理

必须必须必须先清晰思路,再写代码。

int strStr2(string haystack, string needle) {
        // 时间复杂度O(m*n),不能满足leetcode的时间要求
        int m = needle.size();
        int n = haystack.size();
        if (m == 0) return 0;
        if (m > n) return -1;
        for (int i = 0; i < n; i++) {
            int j = 0;
            if (haystack[i] == needle[j]) {
                for (; j < m && i+j < n; j++) {
                    if (needle[j] != haystack[i+j])
                        break;
                }
                if (j == m)
                    return i;
            }
        }
        return -1;
    }

思路二 Rabin–Karp algorithm算法 - Hash 查找

Rabin–Karp algorithm算法:是计算机科学中通过 hash 的方法用于在一个大量文本中查找一个固定长度的字符串的算法。(模式查找)

从思路一我们可知,要想确定haystack中存在needle,必须完全比较needle的所有字符。那么有没有能够利用上一次比较的结果,仅添加O(1)的时间。

基本思想是:用一个hash code 表示一个字符串,为了保证 hash 的唯一性,我们用比字符集大的素数为底,以这个素数的幂为基。

例如:小写字母集,选择素数29为底,如字符串”abcd”的hash code为

hash=1?290+2?291+3?292+4?293

那么下一步计算字符串”bcde”的 hash code 为

hash=hash/29+5?293

这一计算过程是O(1) 常量的操作,那么检测所有子串所需的时间复杂度是O(m+(n-m)) = O(n)是一个线性算法(Rolling hash

<注>例子中是正序计算的hash code,以下程序中使用是倒序计算的 hash code, 即

hash("abcd")=4?290+3?291+2?292+1?293,类似于进制转换

hash("bcde")=(hash("abcd")?1?293)?29+5

    int charToInt(char c) {
        return (int)(c-‘a‘+1);
    }
    // 时间复杂度 O(m+(n-m)) = O(n)
    int strStr(string haystack, string needle) {
        int m = needle.size();
        int n = haystack.size();
        if (m == 0) return 0;
        if (m > n) return -1;

        const int base = 29;
        long long max_base = 1;
        long long needle_code = 0;
        long long haystack_code = 0;
        for (int j = m - 1; j >= 0; j--) {
            needle_code += charToInt(needle[j])*max_base;
            haystack_code += charToInt(haystack[j])*max_base;
            max_base *= base;
        }
        max_base /= base; // 子串的最大基
        if (haystack_code == needle_code)
            return 0;
        for (int i = m; i < n; i++) {
            haystack_code = (haystack_code - charToInt(haystack[i-m]) * max_base) * base + charToInt(haystack[i]);
            if (haystack_code == needle_code)
                return i - m + 1;
        }
        return -1;
    }

存在的缺点是,素数的幂可能会很大,因此计算结果要使用 long long 的类型 ,甚至要求更大的big int;另外,可以通过取余的方式缩小,但是有小概率误判。

算法参考:http://blog.csdn.net/linhuanmars/article/details/20276833

更多思路

KMP字符串搜索算法:

http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html

https://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm

Boyer-Moore字符串搜索算法

http://www.ruanyifeng.com/blog/2013/05/boyer-moore_string_search_algorithm.html

https://zh.wikipedia.org/wiki/Boyer-Moore%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%90%9C%E7%B4%A2%E7%AE%97%E6%B3%95

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-15 19:45:32

leetcode | Implement strStr() | 实现字符串查找函数的相关文章

leetcode——Implement strStr() 实现字符串匹配函数(AC)

Implement strStr(). Returns a pointer to the first occurrence of needle in haystack, or null if needle is not part of haystack. 这个题考查的是KMP算法.先求特征向量,然后再进行匹配,确实能够大大提高效率.code例如以下: class Solution { public: char *strStr(char *haystack, char *needle) { if(

LeetCode: Implement strStr() [027]

[题目] Implement strStr(). Returns a pointer to the first occurrence of needle in haystack, or null if needle is not part of haystack. [题意] 实现库函数strStr(), 功能是在字符串haystack中找出目标串needle第一次出现的索引位 [思路]字符串的匹配,能够用暴力解法,但不推荐.一般使用KMP算法求解. 简要介绍一下KMP的思想: haystack是

有意思的字符串查找函数

通过一段时间对字符串的了解,我发现了许多有意思的字符串函数,下面我们就以常见的字符串查找函数:strchr,strrchr,strstr,strrstr为例来模拟实现这些有意思的字符串查找函数. [strchr][strrchr] 查找一个字符,有所不同的是:strchr用于查找这个字符第一次出现的位置,strrchr用于查找这个字符最后一次出现的位置.下面我们就来打开MSDN来查找这两个字符查找函数的函数原型: char *strchr(const char *string,int c) ch

[LeetCode] Implement strStr() [18]

题目 Implement strStr(). Returns a pointer to the first occurrence of needle in haystack, or null if needle is not part of haystack. 原题链接(点我) 解题思路 字符串匹配这也是个老题了,方法主要有下面4种, 1. 暴利破解法(BF),这个没啥说的,就是一轮一轮的比较,知道遇到相匹配的,这个的时间复杂度为O(n^2). 2. KMP,这应该是字符串匹配领域中最长听说的算

C/C++字符串查找函数 &lt;转&gt;

C/C++ string库(string.h)提供了几个字符串查找函数,如下: memchr 在指定内存里定位给定字符 strchr 在指定字符串里定位给定字符 strcspn 返回在字符串str1里找到字符串str2里的任意一个字符之前已查找的字符数量 strrchr 在字符串里定位给定字符最后一次出现的位置 strpbrk 在字符串str1里定位字符串str2里任意一个首次出现的字符 strspn 返回字符串str1从开始字符到第一个不在str2中的字符个数 strstr 在字符串str1中

c#中的字符串查找函数

indexOf()方法,查找某字符串在一个字符串内的位置,没有则返回-1string aa="abcdef";int a=aa.indexOf("bc");//a会等于1int b=aa.indexOf("a");//b会等于0int c=aa.indexOf("g");c会等于-1所以你只要判断返回出来的int值是不是小于0就知道这个字符串里有没有包含指定的另一个字符串 c#中的字符串查找函数,布布扣,bubuko.com

[Leetcode] implement strStr() (C++)

题目: Implement strStr(). Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack. Update (2014-11-02):The signature of the function had been updated to return the index instead of the pointer. If you st

LeetCode Implement strStr()

Implement strStr(). Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack. Update (2014-11-02): The signature of the function had been updated to return the index instead of the pointer. If you still

字符串查找函数(BF)

//模拟字符串定位函数 // s: abcbbghi // t: ghi // 返回6 #include <iostream> #include <string> #include <algorithm> using namespace std; int main() { string s, t; int len1, len2; int i, j; while(cin>>s) { cin>>t; len1=s.size(); len2=t.siz