In computer science, the Knuth-Morris-Pratt string lookup algorithm (abbreviated as the KMP algorithm) looks for the occurrence of a word W in a string S (or the number of occurrences of W in S). The algorithm takes advantage of the fact that a word when mismatched contains enough information on its own to determine where the next match is likely to start to avoid rechecking previously matched characters.

// Find the index of the first occurrence of Pattern in text. If not, return -1.
// Convention: Return 0 as long as pattern is an empty string
func FirstIndex(text, pattern string) int {
    if pattern == "" {
        return 0
    } else if text == "" {
        return - 1
    }
    // text ! = "" && pattern ! = ""
    var (
        tl = len(text)
        pl = len(pattern)
    )
    if tl < pl {
        return - 1
    }
    // tl >= pl
    return indexKMP(text, pattern)
}

func indexKMP(text, pattern string) int {
    var (
        ti int
        pi int
        tl = len(text)
        pl = len(pattern)
        next = getNextArray(pattern)
    )
    for ti < tl {
        if text[ti] == pattern[pi] {
            ti++
            pi++
            if pi == pl {
                return ti-pl
            }
        } else if pi == 0 {
            ti++
            if tl-ti < pl {
                break}}else {
            pi = next[pi- 1]
            if tl-ti < pl-pi {
                break}}}return - 1
}

func getNextArray(p string) []int {
    // Preconditions: p is not an empty string
    if p == "" {
        panic("p is empty")}var (
        j    int // Prefix the current index
        i    = 1 // suffix current index
        l    = len(p)
        next = make([]int, l)
    )
    // next[0] = 0, implicit initialization
    for i < l {
        if p[j] == p[i] {
            j++
            next[i] = j
            i++
        } else if j == 0 {
            next[i] = 0
            i++
        } else {
            j = next[j- 1]}}return next
}
Copy the code