我直接上代码,需要了解相关原理的可以看一下 https://blog.csdn.net/v_JULY_v/article/details/7041827 我也是看的这个以及其他资料学习的
package main
//暴力匹配
func ViolenceMatch(s , p string) int {
i := 0 // 主串的位置
j := 0 // 模式串的位置
for i < len(s) && j < len(p){
if s[i] == p[j] { // 当两个字符相同,就比较下一个
i++
j++
} else {
i = i - j + 1 // 一旦不匹配,i后退
j = 0 // j归0
}
}
if j == len(p) {
return i - j
} else {
return -1
}
}
func GetNext(s string) []int {
next := make([]int, len(s) +1 )
next[0] = -1
k := -1
j := 0
for j < len(s) -1 {
//fmt.Println("k=",k,"j=",j, "next =",next)
//这里,k表示next[j-1],且s[k]表示前缀,s[j]表示后缀
//注:k==-1表示未找到k前缀与k后缀相等,首次分析可先忽略
if k == -1 || s[j] == s[k] {
j++
k++
next[j+1] = k
} else { //s[j]与s[k]不匹配,继续递归计算前缀s[next[k]]
k = next[k]
}
}
return next
}
func Kmp(s, p string,next []int) int {
i,j := 0,0
for i < len(s) && j < len(p) {
if j == -1 || s[i] == p[j] {
i++
j++
}else {
j = next[j]
}
}
if j == len(p) {
return i - j
}
return -1
}
上面就是 实现的 暴力匹配和 kmp 实现,不过我发现一个有趣的事情,压测的时候暴力比kmp快哦,
下面我直接上压测的代码,感兴趣的可以自己测试一下,应该和字符串的长短有关系。
package main
import (
"testing"
"strings"
)
var (
str = "abababbcabcac"
p = "abc"
)
func VM() {
ViolenceMatch(str,p)
}
//kmp 算法
func KmpSearch() {
Kmp(str,p,GetNext(p))
}
//官方使用的 Rabin-Karp search
func RKSearch() {
strings.Index(str,p)
}
func BenchmarkKmp(b *testing.B) {
for i := 0; i < b.N; i++ {
KmpSearch()
}
}
func BenchmarkPK(b *testing.B) {
for i := 0; i < b.N; i++ {
RKSearch()
}
}
func BenchmarkVM(b *testing.B) {
for i := 0; i < b.N; i++ {
VM()
}
}