feat(Go-Tool):

2021/03/02: 新增字符串匹配 暴力匹配、KMP匹配、SunDay匹配算法
            2021/03/02: 修复Rand包随机获取方法
This commit is contained in:
Huangzj
2021-03-02 13:33:07 +08:00
parent 74dd19c675
commit dc5d924a2c
13 changed files with 385 additions and 7 deletions
+2
View File
@@ -23,4 +23,6 @@ func TestHorspool(t *testing.T) {
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "kdasdsad")) //输出-1
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "dsadsa")) //输出-1
fmt.Println(shiTable("abdabe"))
}
+55
View File
@@ -0,0 +1,55 @@
/*
* @Author : huangzj
* @Time : 2021/2/24 13:19
* @DescriptionKMP字符串匹配算法,参考地址:https://www.cnblogs.com/en-heng/p/5091365.html
* http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html
*/
package stringMatch
func KmpMatch(allString string, match string) int {
next := getNext(match)
i := 0 //被匹配的字符串下标
j := 0 //模式匹配字符串下标
sLength := len(allString) - 1
mLength := len(match) - 1
for i <= sLength && j <= mLength {
if j == -1 || allString[i] == match[j] {
j++
i++
} else {
j = next[j]
}
}
if j == len(match) {
return i - j
}
return -1
}
//失配表函数构建(部分匹配函数)
func getNext(match string) []int {
next := make([]int, len(match))
next[0] = -1
i := 0
j := -1
mLength := len(match) - 1
for i < mLength {
//处理两种情况: 1.数组第一个数是-1 2. match对应位置字符相等的情况
if j == -1 || match[i] == match[j] {
//如果这里是数组第一个数的时候,下标要往后移动
//如果这里是数组相等的情况,要比较下一个相应的字符,所以下标需要往后移动,而next需要在上一个的基础上去做+1操作
i++
j++
next[i] = j
} else {
//如果匹配过程中,出现对应不上的情况,也就是说 match[i] != match[j],
j = next[j]
}
}
return next
}
+54
View File
@@ -0,0 +1,54 @@
/*
* @Author : huangzj
* @Time : 2021/2/24 17:52
* @Description
*/
package stringMatch
import (
"fmt"
"testing"
)
func TestKmpMatch(t *testing.T) {
s := "abcbvxs"
m := "bcb"
showResult(s, m)
s = "abcbvxs"
m = "bx"
showResult(s, m)
s = "abcbvxssdaadsad"
m = "cbvxssdaa"
showResult(s, m)
}
func TestMatchNum(t *testing.T) {
s := "ababababca"
m := "abababca"
showResult(s, m)
}
func showResult(s, m string) {
i := KmpMatch(s, m)
if i == -1 {
fmt.Println("未找到对应字符串")
} else {
fmt.Println(fmt.Sprintf("匹配到的字符串是:%v", s[i:len(m)+i]))
}
}
func TestGetNext(t *testing.T) {
next := getNext("abababca")
fmt.Println(next)
next1 := getNext("abababc")
fmt.Println(next1)
next2 := getNext("abababcxy")
fmt.Println(next2)
next3 := getNext("abababcxyxyy")
fmt.Println(next3)
next4 := getNext("abcdabd")
fmt.Println(next4)
next5 := getNext("abcxabcxabcyabcz")
fmt.Println(next5)
}
+45
View File
@@ -0,0 +1,45 @@
/*
* @Author : huangzj
* @Time : 2021/3/2 11:21
* @Description
*/
package stringMatch
func ShiftTable(modeString string) []int {
shiftTable := make([]int, 256)
//一开始设置所有的字符匹配不上向右移动大小为:模式字符串长度 + 1(因为要移动到下一个字符的后一位)
for i := range shiftTable {
shiftTable[i] = len(modeString) + 1
}
//设置模式字符串中每一个字符的移动长度.
for i := range modeString {
shiftTable[modeString[i]-'a'] = len(modeString) - i
}
return shiftTable
}
func SundayMatch(allString, modeString string) int {
table := ShiftTable(modeString)
aLength := len(allString)
mLength := len(modeString)
i := 0 //这个参数记录的是移动过程中,,模式字符串对应原始字符串的第一个位置.
for i < aLength-mLength {
j := 0
for allString[i+j] == modeString[j] {
j++
if j >= len(modeString) {
return i
}
}
//找到移动后模式字符串对应原始字符串的第一个位置
move := allString[i+mLength]
i = i + table[move-'a']
}
return -1
}
+33
View File
@@ -0,0 +1,33 @@
/*
* @Author : huangzj
* @Time : 2021/3/2 11:21
* @Description
*/
package stringMatch
import (
"fmt"
"testing"
)
func TestSundayMatch(t *testing.T) {
s := "abcbvxs"
m := "bcb"
showResult2(s, m)
s = "abcbvxs"
m = "bx"
showResult2(s, m)
s = "abcbvxssdaadsad"
m = "cbvxssdaa"
showResult2(s, m)
}
func showResult2(s, m string) {
i := SundayMatch(s, m)
if i == -1 {
fmt.Println("未找到对应字符串")
} else {
fmt.Println(fmt.Sprintf("匹配到的字符串是:%v", s[i:len(m)+i]))
}
}
+32
View File
@@ -0,0 +1,32 @@
/*
* @Author : huangzj
* @Time : 2021/2/25 11:11
* @Description
*/
package stringMatch
func ViolentMatch(allString, match string) int {
i := 0
j := 0
sLength := len(allString)
mLenght := len(match)
for i < sLength && j < mLenght {
//当前字符如果匹配,继续匹配下一个字符,坐标移动
if allString[i] == match[j] {
j++
i++
} else {
//如果字符不匹配,match从头开始,被匹配的字符串从之前匹配的下一个字符开始,坐标修改
i = i - j + 1
j = 0
}
}
if j == len(match) {
return i - j
}
return -1
}
+33
View File
@@ -0,0 +1,33 @@
/*
* @Author : huangzj
* @Time : 2021/2/25 11:11
* @Description
*/
package stringMatch
import (
"fmt"
"testing"
)
func TestViolentMatch(t *testing.T) {
s := "abcbvxs"
m := "bcb"
showResult1(s, m)
s = "abcbvxs"
m = "bx"
showResult1(s, m)
s = "abcbvxssdaadsad"
m = "cbvxssdaa"
showResult1(s, m)
}
func showResult1(s, m string) {
i := ViolentMatch(s, m)
if i == -1 {
fmt.Println("未找到对应字符串")
} else {
fmt.Println(fmt.Sprintf("匹配到的字符串是:%v", s[i:len(m)+i]))
}
}