func z(s string) []int { // Use Z-algorithm to preprocess given string. See // Gusfield for complete description of algorithm. Z := make([]int, len(s)+1) Z[0] = len(s) // Initial comparison of s[1:] with prefix for i := 1; i < len(s); i++ { if s[i] == s[i-1] { Z[1] += 1 } else { break } } r, l := 0, 0 if Z[1] > 0 { r, l = Z[1], 1 } for k := 2; k < len(s); k++ { if k > r { // Case 1 for i := k; i < len(s); i++ { if s[i] == s[i-k] { Z[k] += 1 } else { break } } r, l = k + Z[k] - 1, k } else { // Case 2 // Calculate length of beta nbeta := r - k + 1 Zkp := Z[k - l] if nbeta > Zkp { // Case 2a: Zkp wins Z[k] = Zkp } else { // Case 2b: Compare characters just past r nmatch := 0 for i := r+1; i < len(s); i++ { if s[i] == s[i - k] { nmatch += 1 } else { break } } l, r = k, r + nmatch Z[k] = r - k + 1 } } } return Z } z("abracadabra") // abracadabra (11) // a (1) // a (1) // abra (4) // a (1) z("aaaaa") func zMatch(p, t string) []int { s := p + "$" + t Z := z(s) occurrences := []int{} for i := len(p) + 1; i < len(s); i++ { if Z[i] >= len(p) { occurrences = append(occurrences, i - (len(p) + 1)) } } return occurrences } zMatch("needle", "haystack needle haystack") // 012345678901234567890123 // 1 2 zMatch("needle", "haystack needle needle") // 0123456789012345678901 // 1 2