feat(Go-Tool):
2021/03/02: 新增字符串匹配 暴力匹配、KMP匹配、SunDay匹配算法
2021/03/02: 修复Rand包随机获取方法
This commit is contained in:
@@ -60,7 +60,7 @@
|
||||
|
||||
2020/11/25:完善linq包使用示例
|
||||
|
||||
2020/12/7 :更新bit位操作工作 BitTool
|
||||
2020/12/7 : 更新bit位操作工作 BitTool
|
||||
|
||||
2020/12/15:添加前缀树工具,实现前缀搜索和字符串搜索功能
|
||||
|
||||
@@ -68,7 +68,9 @@
|
||||
|
||||
2020/12/31:新增项目案例(角色技能树)
|
||||
|
||||
2021/2/5: 新增二分查找区间内数值方法
|
||||
2021/02/05: 新增二分查找区间内数值方法
|
||||
|
||||
2021/03/02: 新增字符串匹配 暴力匹配、KMP匹配、SunDay匹配算法
|
||||
|
||||
# 修复日志
|
||||
2020/11/23:修改项目案例(按照一定规则对一组数据进行排序分组)
|
||||
@@ -79,11 +81,13 @@
|
||||
|
||||
2020/12/31:删除源码学习部分,挪到Go-Study工程
|
||||
|
||||
2021/1/4 :reflectM包添加indirect处理指针和非指针,获取type、value
|
||||
2021/01/04:reflectM包添加indirect处理指针和非指针,获取type、value
|
||||
|
||||
2021/02/18:bitStore新增特殊档位获取方法,修改档位数目的参数标识
|
||||
|
||||
2021/02/23:删除linq包使用示例,修改二进制工具与单测类,修改lomuto划分,修改前缀树与单测类,修改时间比较工具
|
||||
2021/02/23: 删除linq包使用示例,修改二进制工具与单测类,修改lomuto划分,修改前缀树与单测类,修改时间比较工具
|
||||
|
||||
2021/03/02: 修复Rand包随机获取方法
|
||||
|
||||
# mod vendor模式加载包
|
||||
通过go mod的方式加载的github上面的包会有报红的问题,但是包本身是可以运行的,这样就是会有一个问题,如果你想要点击去看方法的内容,没办法做到
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/2/23 20:52
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package rand
|
||||
|
||||
type AwardWeight struct {
|
||||
Award interface{} //奖励数据
|
||||
Weight int //权重
|
||||
}
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2020/6/29 10:48
|
||||
* @Description:这边的随机获取没有加锁,对于一些需要加锁的场景可以在外面再包装一层
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package rand
|
||||
@@ -47,7 +47,7 @@ func GetRandIntNoRepeat(count, min, max int) []int {
|
||||
return randAttr
|
||||
}
|
||||
|
||||
//从一个数组中获取到X个不重复随机数
|
||||
//从一个数组中获取到X个不重复下标的随机数
|
||||
func GetDiffNum(data []int, count int) []int {
|
||||
if count > len(data) {
|
||||
panic("获取随机数数量有误")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2020/6/29 10:23
|
||||
* @Description:这边的随机获取没有加锁,对于一些需要加锁的场景可以在外面再包装一层
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package rand
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/2/23 20:50
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package rand
|
||||
|
||||
func GetAwardWeightByWeight(awardWeight []*AwardWeight) *AwardWeight {
|
||||
//求总权重
|
||||
weight := 0
|
||||
for _, award := range awardWeight {
|
||||
weight += award.Weight
|
||||
}
|
||||
randNum := GetRandInt(1, weight)
|
||||
sum := 0
|
||||
for _, award := range awardWeight {
|
||||
sum += award.Weight
|
||||
if sum >= randNum {
|
||||
return award
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//根据权重不放回的抽取,出参是:抽到的道具、剩余没有抽的道具
|
||||
func GetByWeightWithLeftAward(awardWeight []*AwardWeight) (*AwardWeight, []*AwardWeight) {
|
||||
weight := 0
|
||||
leftAwards := make([]*AwardWeight, 0)
|
||||
for _, award := range awardWeight {
|
||||
weight += award.Weight
|
||||
}
|
||||
randNum := GetRandInt(1, weight)
|
||||
sum := 0
|
||||
for index, award := range awardWeight {
|
||||
sum += award.Weight
|
||||
if sum >= randNum {
|
||||
//如果获取到奖励则将当前获取的奖励扣除
|
||||
leftAwards = append(awardWeight[0:index], awardWeight[index+1:]...)
|
||||
return award, leftAwards
|
||||
}
|
||||
}
|
||||
return nil, leftAwards
|
||||
}
|
||||
|
||||
// 根据权重不放回的抽取X个元素,直接返回这些元素
|
||||
// 入参:奖池、抽取数量,出参:获得的所有道具,剩余的其他道具
|
||||
func GetSomeAwardsFromPool(srcAwardPool []*AwardWeight, count int) ([]*AwardWeight, []*AwardWeight) {
|
||||
if count > len(srcAwardPool) {
|
||||
panic("抽取数量不对")
|
||||
}
|
||||
var finalAwardList []*AwardWeight
|
||||
var award *AwardWeight
|
||||
var leftAward = make([]*AwardWeight, len(srcAwardPool))
|
||||
copy(leftAward, srcAwardPool)
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
award, leftAward = GetByWeightWithLeftAward(leftAward)
|
||||
finalAwardList = append(finalAwardList, award)
|
||||
}
|
||||
return finalAwardList, leftAward
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/2/23 22:08
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
package rand
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRandByAwardWeight(t *testing.T) {
|
||||
awardList := make([]*AwardWeight, 0)
|
||||
awardList = append(awardList, &AwardWeight{
|
||||
Award: []int{1, 2},
|
||||
Weight: 10,
|
||||
})
|
||||
awardList = append(awardList, &AwardWeight{
|
||||
Award: []int{2, 2},
|
||||
Weight: 20,
|
||||
})
|
||||
awardList = append(awardList, &AwardWeight{
|
||||
Award: []int{3, 2},
|
||||
Weight: 30,
|
||||
})
|
||||
|
||||
award := GetAwardWeightByWeight(awardList)
|
||||
fmt.Println(award.Award)
|
||||
|
||||
award1, list3 := GetByWeightWithLeftAward(awardList)
|
||||
fmt.Println(award1.Award)
|
||||
for _, award := range list3 {
|
||||
fmt.Println(award.Award)
|
||||
}
|
||||
|
||||
list4, left := GetSomeAwardsFromPool(awardList, 2)
|
||||
for _, award := range list4 {
|
||||
fmt.Println(award.Award)
|
||||
}
|
||||
for _, award := range left {
|
||||
fmt.Println(award.Award)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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"))
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* @Author : huangzj
|
||||
* @Time : 2021/2/24 13:19
|
||||
* @Description:KMP字符串匹配算法,参考地址: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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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]))
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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]))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user