LeetCode 28. 实现 strStr()

java KMP + 字符串哈希两种方法

KMP

KMP不多说了,先计算 n e x t [ ] next[] next[]数组,再逐个匹配即可。

class Solution {
    public int strStr(String haystack, String needle) {
        if(needle.length() == 0) return 0;
        char[] s = haystack.toCharArray(), p = needle.toCharArray();
        int[] ne = new int[p.length];
        for(int i = 1, j = 0; i < p.length; i++){
            while(j > 0 && p[i] != p[j]) j = ne[j - 1];
            if(p[i] == p[j]) j++;
            ne[i] = j;
        }
        for(int i = 0, j = 0; i < s.length; i++){
            while(j > 0 && s[i] != p[j]) j = ne[j - 1];
            if(s[i] == p[j]) j++;
            if(j == p.length) return i - p.length + 1;
        }
        return -1;
    }
}

时间复杂度

KMP时间复杂度 O ( n ) O(n) O(n)

空间复杂度

额外 n e x t [ ] next[] next[]数组,使用 O ( m ) O(m) O(m)额外空间, m m m为匹配串长度。

字符串哈希

计算 h a y s t a c k haystack haystack字符串的哈希前缀和,想要计算任意一段字串的哈希值的时候只需要使用 h [ r ] − h [ l − 1 ] ∗ p [ r − l + 1 ] h[r] - h[l - 1] * p[r - l + 1] h[r]h[l1]p[rl+1]公式即可计算,相当于将 [ 0 , l ] [0,l] [0,l]左移 r − l + 1 r-l+1 rl+1位之后减掉,这样就剩下 [ l , r ] [l,r] [l,r]区间的字符串哈希了。再循环一遍比较每一部分的字符串哈希是否与 n e e d l e needle needle的哈希相同即可。

这里哈希过程中的 P P P值取 31 31 31的原因,是因为 j a v a java java S t r i n g . h a s h C o d e ( ) String.hashCode() String.hashCode()方法中,取值为 31 31 31,对标一下,就可以直接使用其 h a s h C o d e ( ) hashCode() hashCode()方法进行计算了。

class Solution {
    int P = 31;
    int[] h, p;
    int get(int l, int r){
        return h[r] - h[l - 1] * p[r - l + 1];
    }
    public int strStr(String haystack, String needle) {
        if(needle.length() == 0) return 0;
        h = new int[haystack.length() + 1];
        p = new int[haystack.length() + 1];
        char[] str = haystack.toCharArray();
        char[] ptr = needle.toCharArray();
        int hashcode = needle.hashCode();
        p[0] = 1;
        for(int i = 1; i <= str.length; i ++){
            h[i] = h[i - 1] * P + str[i - 1];
            p[i] = p[i - 1] * P;
        }
        for(int i = 1; i <= str.length - ptr.length + 1; i++){
            if(hashcode == get(i, i + ptr.length - 1)) return i - 1;
        }
        return -1;

    }
}

时间复杂度

O ( n ) O(n) O(n)级别复杂度,两次循环都为 O ( n ) O(n) O(n)

空间复杂度

O ( n ) O(n) O(n)级别额外空间。

我的博客:https://me.csdn.net/qq_20067165?ref=miniprofile

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值