[top]
#golang学习
定义网上很多,就不在描述了。
func getNext(data []string) []int {
dataLen := len(data)
next := make([]int, dataLen)
next[0] = 0;
for i := 1; i < dataLen; i++ {
preSufIndex := next[i-1]; //前缀后缀的最长公共子串长度,那么preSufIndex就是指那个字符的后一个字符,下标从0开始
for {
if (data[preSufIndex] == data[i]) {
next[i] = preSufIndex + 1
break
} else {
preSufIndex = next[preSufIndex]
}
if (preSufIndex == 0) {
next[i] = 0
break
}
}
}
return next
}
根据以上代码,可以得出next 求的是前缀后缀的最长公共子串长度 。 举个例子, 例如 主串: abcdabcfabcesaf 模式串: abcdabce 当主串f 和模式串e 不匹配时,则回退的长度是除当前字符外,前缀后缀的最长公共子串长度 。 所以每次需要回退的长度为next[index-1]。 出于这种情况,next数组可以优化为:保存除当前字符外,前缀后缀的最长公共子串长度。 同时,根据前面的代码,会发现next[0]是特殊情况,可以使用一个特别的数字来代替,优化代码
func getNextNew(data []string) []int {
dataLength := len(data)
next := make([]int, dataLength)
next[0] = -1
k := -1
index := 0
for index < dataLength-1 {
if k == -1 || data[index] == data[k] {
k++
index++
next[index] = k
} else {
k = next[k]
}
}
return next
}
这个代码,也是网上很多博客晒出获取next数组的代码。
在举个例子
主串: abacedas 模式串: abab 当主串c和模式串b不匹配时, b会回退到下标1,这时候1上的字符也是b。和主串c肯定是不匹配的,针对这种情况,模式串回退到下标0,是最优的。 优化后的代码
func getNextNew(data []string) []int {
dataLength := len(data)
next := make([]int, dataLength)
next[0] = -1
k := -1
index := 0
for index < dataLength-1 {
if k == -1 || data[index] == data[k] {
k++
index++
if data[index] == data[k] {
next[index] = next[k]
} else {
next[index] = k
}
} else {
k = next[k]
}
}
return next
}