diff --git a/main.go b/main.go index 70385bc..c285317 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,8 @@ package main import ( + "fmt" + . "github.com/ehlxr/leetcode-go/src" ) @@ -22,7 +24,12 @@ func main() { // rs := []rune(s) // println(string(rs[6])) - s := "babad" - println(LongestPalindrome(s)) + // s := "babad" + // println(LongestPalindrome(s)) + s := "bacbababaabcbab" + p := "ababa" + // fmt.Printf("%+v\n", GetNext(p)) + fmt.Printf("%+v\n", Kmp(s, p)) + fmt.Printf("%+v", Bf(s, p)) } diff --git a/src/string_match.go b/src/string_match.go new file mode 100644 index 0000000..ba9776d --- /dev/null +++ b/src/string_match.go @@ -0,0 +1,89 @@ +package src + +// 暴力匹配 +func Bf(s, p string) int { + n := len(s) + m := len(p) + if n < m { + return -1 + } + + for i := 0; i <= n-m; i++ { + j := 0 + for j < m { + // 如果主串与模式串不匹配,则主串向右移动一个字符,模式串从头开始匹配 + if s[i+j] != p[j] { + break + } + j++ + } + if j == m { + return i + } + } + + return -1 +} + +func Kmp(s, p string) int { + n := len(s) + m := len(p) + if n < m { + return -1 + } + next := GetNext(p) + + for i := 0; i <= n-m; i++ { + j := 0 + for j < m { + // 暴力匹配算法当模式串和主串不匹配时,主串匹配下标 +1,模式串匹配下标置为 0, + // KMP 算法优化点在于将模式串下标置为不匹配字符前一个字符对应 next 数组的值 + if s[i+j] != p[j] { + // 当模式串与主串不匹配时,如果不匹配字符对应模式串下标大于 j > 0 (非首个模式串字符), + // 并且此字符前一个字符对应字符串部分匹配表中的值 next[j - 1] 也大于 0, + // j - next[j - 1] 即模式串为后移的位数,等价于 j 置为 next[j - 1] + + if j != 0 && next[j-1] != 0 { + // j 后移 j-next[j-1],等价于 j = next[j-1] + j = next[j-1] + } else { + break + } + } + j++ + } + if j == m { + return i + } + } + + return -1 +} + +func GetNext(p string) []int { + n := len(p) + next := make([]int, n) + next[0] = 0 + k := 0 + + // 根据已知 next 数组的前 i-1 位推测第 i 位 + for i := 1; i < n; i++ { + for k > 0 && p[k] != p[i] { + // k 为 p[0, i) 子串最大匹配前后缀长度 + // p[0, k) 为 p[0, i) 子串最大匹配前缀子串 + + // 若:1、p[k] != p[i],则求 p[0, i] 子串最大匹配前后缀长度问题 + // 转换成了求 p[0, k) 子串最大匹配前后缀长度问题 + // 循环直到 p[k] == p[i] (下一步处理) 或 k == 0 + k = next[k] + } + + // 若:2、p[k] == p[i],则 p[0, i] 子串最大匹配前后缀长度为 k + 1 + if p[k] == p[i] { + k++ + } + + next[i] = k + } + return next +}