Leetcode 28. 实现 strStr() 题解

题目链接:https://leetcode-cn.com/problems/implement-strstr/
Leetcode 28. 实现 strStr() 题解_第1张图片
最简单的方法是遍历搜索,复杂度为O(NL),其中N和L分别为两个字符串的长度。

这里说一下“Rabin Karp - 常数复杂度”算法,只需要O(N)的复杂度:

字符串中均为小写字母,故经过 needle[i] - 'a’的处理可将其化为 0 - 25 范围内的数值,可以用“哈希码”表示:
Leetcode 28. 实现 strStr() 题解_第2张图片
对于这道题,可简单设 a = 26,这样不同字符串对应的哈希码一定不同。所以计算出 needle 的哈希码后,只需要滑动窗口计算 haystack 中长度为 needle.size() 的子串的哈希码即可。

代码如下:
(1)遍历搜索:

class Solution {
public:
    int strStr(string haystack, string needle) {
        if(needle == "") {
            return 0;
        }
        if(haystack == "") {
            return -1;
        }
        if(haystack.size() < needle.size()) {
            return -1;
        }
        int pos = -1;
        for(int i = 0; i <= haystack.size() - needle.size(); i++) {
            bool ok = true;
            for(int j = 0; j < needle.size(); j++) {
                if(haystack[i + j] != needle[j]) {
                    ok = false;
                    break;
                }
            }
            if(ok) {
                pos = i;
                break;
            }
        }
        return pos;
    }
};

(2)哈希码算法:

typedef long long ll;
ll m = 2147483648;

class Solution {
public:
    ll poww(int a, int b) {	//快速幂
        ll res = 1, base = a;
        while(b) {
            if(b & 1) {
                res = (res * base) % m;
            }
            base = (base * base) % m;
            b >>= 1;
        }
        return res;
    }

    int strStr(string haystack, string needle) {
        if(haystack.size() < needle.size()) {	//特判
            return -1;
        }
        ll need = 0, now = 0;
        for(int i = 0; i < needle.size(); i++) {
            need = ((need * 26) % m + needle[i] - 'a') % m;
            now = ((now * 26) % m + haystack[i] - 'a') % m;
            //printf("need = %lld, now = %lld\n", need, now);
        }
        //printf("初始化完成, need = %lld, now = %lld\n", need, now);
        if(need == now) {
            return 0;
        }
        for(int j = 1; j < haystack.size() - needle.size() + 1; j++) {
            now = (now - ((haystack[j - 1] - 'a') * poww(26, needle.size() - 1)) % m + m) % m;
            //printf("滑动窗口 1, now = %lld\n", now);
            now = ((now * 26) % m + (haystack[j + needle.size() - 1] - 'a')) % m;
            //printf("滑动窗口 2, now = %lld\n\n", now);
            if(now == need) {
                return j;
            }
        }
        return -1;
    }
};

你可能感兴趣的:(Leetcode,双指针_滑动窗口)