Skip to content
Snippets Groups Projects
bytes.go 27 KiB
Newer Older
  • Learn to ignore specific revisions
  • func indexRabinKarp(s, sep []byte) int {
    	// Rabin-Karp search
    	hashsep, pow := hashStr(sep)
    	n := len(sep)
    	var h uint32
    	for i := 0; i < n; i++ {
    		h = h*primeRK + uint32(s[i])
    	}
    	if h == hashsep && Equal(s[:n], sep) {
    		return 0
    	}
    	for i := n; i < len(s); {
    		h *= primeRK
    		h += uint32(s[i])
    		h -= pow * uint32(s[i-n])
    		i++
    		if h == hashsep && Equal(s[i-n:i], sep) {
    			return i - n
    		}
    	}
    	return -1
    }
    
    // primeRK is the prime base used in Rabin-Karp algorithm.
    const primeRK = 16777619
    
    // hashStr returns the hash and the appropriate multiplicative
    // factor for use in Rabin-Karp algorithm.
    func hashStr(sep []byte) (uint32, uint32) {
    	hash := uint32(0)
    	for i := 0; i < len(sep); i++ {
    		hash = hash*primeRK + uint32(sep[i])
    	}
    	var pow, sq uint32 = 1, primeRK
    	for i := len(sep); i > 0; i >>= 1 {
    		if i&1 != 0 {
    			pow *= sq
    		}
    		sq *= sq
    	}
    	return hash, pow
    }
    
    
    // hashStrRev returns the hash of the reverse of sep and the
    // appropriate multiplicative factor for use in Rabin-Karp algorithm.
    func hashStrRev(sep []byte) (uint32, uint32) {
    	hash := uint32(0)
    	for i := len(sep) - 1; i >= 0; i-- {
    		hash = hash*primeRK + uint32(sep[i])
    	}
    	var pow, sq uint32 = 1, primeRK
    	for i := len(sep); i > 0; i >>= 1 {
    		if i&1 != 0 {
    			pow *= sq
    		}
    		sq *= sq
    	}
    	return hash, pow
    }