#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.


这题brute force肯定要bug free, 如果能打出来O(n)的解法肯定加分, rolling hash解法必须掌握

下面的解法用3做base,Integer范围内不会溢出, 但是还是用Robin Karp的方法取余比较好, EPI上有这题的解法, 参悟一下再来update。

// https://jixiangsanbao.wordpress.com/2014/04/26/implement-strstr/
// http://blog.csdn.net/linhuanmars/article/details/20276833
public class Solution {
    public int strStr(String haystack, String needle) {
        if(haystack == null || needle == null || needle.length() == 0){
            return 0;
        }
        if(haystack.length() < needle.length()){
            return -1;
        }
        int base = 3; // 如果用大的base, 比如 7 或者 29, 31, 数值太大会溢出, 导致hash计算不对
        // 比较细心的朋友可能看出来了,这个方法的hashcode比较容易越界,因为以素数为底的幂会很大,解决的办法可以用BigInteger,或者如同Rabin–Karp algorithm - Wikipedia一样对于hashcode进行取余,但是可能存在多个字符串映射到同一hashcode的问题,尽管是很少数的情况。

        int neeHash = getHash(needle, 0, needle.length() - 1, base);
        int hayHash = getHash(haystack, 0, needle.length() - 1, base);
        
        for(int i = 0; i <= haystack.length() - needle.length(); i++){
            // verify if collision
            if(hayHash == neeHash){
                if(haystack.substring(i, i + needle.length()).equals(needle)){
                    return i;
                }
            }
            // calculate new hash
            if(i != haystack.length() - needle.length()){
                hayHash -= ((int)(haystack.charAt(i))) * Math.pow(base, needle.length() - 1);
                hayHash *= base;
                hayHash += (int)(haystack.charAt(i + needle.length()));
            }
        }
        
        return -1;
    }
    
    private int getHash(String s, int start, int end, int base){
        int res = 0;
        int k = end - start;
        for(int i = start; i <= end; i++){
            char c = s.charAt(i);
            res += ((int)c) * Math.pow(base, k--);
        }
        return res;
    }
}


你可能感兴趣的:(LeetCode)