LeetCode 28. Implement strStr()(实现子串定位)

30 篇文章 0 订阅
17 篇文章 0 订阅

原题网址:https://leetcode.com/problems/implement-strstr/

Implement strStr().

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

方法一:穷举。

public class Solution {
    public int strStr(String haystack, String needle) {
        if (needle.length() == 0) return 0;
        if (haystack.length() < needle.length()) return -1;
        char[] ha = haystack.toCharArray();
        char[] na = needle.toCharArray();
        for(int i = 0; i < ha.length && i + na.length <= ha.length; i++) {
            boolean match = true;
            for(int j = 0; j < na.length; j++) {
                if (ha[i + j] != na[j]) {
                    match = false;
                    break;
                }
            }
            if (match) return i;
        }
        return -1;
    }
}

方法二:KMP算法。

public class Solution {
    public int strStr(String haystack, String needle) {
        char[] ha = haystack.toCharArray();
        char[] na = needle.toCharArray();
        int[] kmp = new int[na.length];
        for(int offset=Math.min(na.length-1, ha.length-na.length); offset>0; offset--) {
            for(int i=0; i+offset<na.length; i++) {
                if (na[i] != na[i+offset]) {
                    kmp[i+offset] = offset;
                    break;
                }
            }
        }
        int h = 0, n = 0;
        while (h + na.length <= ha.length && n < na.length) {
            if (ha[h+n] == na[n]) {
                n ++;
            } else if (kmp[n] == 0) {
                h += n + 1;
                n = 0;
            } else {
                h += kmp[n];
                n -= kmp[n];
            }
            if (n == na.length) return h;
        }
        return n == na.length? h : -1;
    }
}

另一种实现:

public class Solution {
    public int strStr(String haystack, String needle) {
        if (needle.length() == 0) return 0;
        if (haystack.length() < needle.length()) return -1;
        char[] ha = haystack.toCharArray();
        char[] na = needle.toCharArray();
        int[] kmp = new int[na.length];
        for(int i = Math.min(ha.length - na.length, na.length - 2); i >= 1; i--) {
            for(int j = i; j < na.length - 1; j++) {
                if (na[j - i] == na[j]) {
                    kmp[j + 1] = i;
                } else {
                    break;
                }
            }
        }

        int h = 0, n = 0;
        while (h + na.length <= ha.length) {
            if (ha[h + n] == na[n]) {
                n++;
                if (n == na.length) return h;
            } else if (kmp[n] == 0) {
                h += Math.max(n, 1);
                n = 0;
            } else {
                h += kmp[n];
                n -= kmp[n];
            }
        }
        return -1;
    }
}

有一篇很牛的KMP算法介绍,参考:http://blog.csdn.net/v_july_v/article/details/7041827


看了上文之后,重新写了一下,把kmp数组看成是最大公共前后缀的长度,这样理解非常方便!

public class Solution {
    public int strStr(String haystack, String needle) {
        if (needle.length() == 0) return 0;
        if (haystack.length() < needle.length()) return -1;
        
        char[] ha = haystack.toCharArray();
        char[] na = needle.toCharArray();
        int[] len = new int[na.length];

        for(int i = 1; i < na.length && i <= ha.length - na.length; i++) {
            int j = len[i - 1];
            while (j > 0 && na[j] != na[i]) j = len[j - 1];
            len[i] = j + (na[j]==na[i]? 1 : 0); 
        }

        int h = 0, n = 0;
        while (h + na.length <= ha.length) {
            if (ha[h + n] == na[n]) {
                n++;
                if (n == na.length) return h;
            } else if (n == 0) {
                h++;
            } else {
                h += n - len[n - 1];
                n = len[n - 1];
            }
        }
        return -1;
    }
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值