Skip to content

Commit 735459b

Browse files
author
willzhen
committed
Add kmp
1 parent 6251477 commit 735459b

File tree

2 files changed

+93
-0
lines changed

2 files changed

+93
-0
lines changed

kmp.go

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package textalg
2+
3+
// Kmp 快速字符串匹配算法,时间复杂度 O(n + m), 其中 n 代表模式串的长度,m 代码匹配母串的长度
4+
type Kmp struct {
5+
pattern string
6+
next []int
7+
}
8+
9+
// BuildKmp 构建 kmp
10+
// patternStr 模式串
11+
func BuildKmp(patternStr string) *Kmp {
12+
kmp := Kmp{
13+
pattern: patternStr,
14+
}
15+
kmp.buildNext(0)
16+
return &kmp
17+
}
18+
19+
func (k *Kmp) buildNext(start int) {
20+
r := []rune(k.pattern)
21+
l := len(r)
22+
// next 要多构建 1 个长度
23+
for i := start; i <= l; i++ {
24+
if i == 0 || i == 1 {
25+
k.next = append(k.next, 0) // next[0] and next[1] is 0
26+
continue
27+
}
28+
j := k.next[i-1]
29+
for ; j > 0 && r[i-1] != r[j]; j = k.next[j] {
30+
}
31+
if r[i-1] == r[j] {
32+
j++
33+
}
34+
k.next = append(k.next, j)
35+
}
36+
}
37+
38+
// AppendPatternStr 扩充模式串长度
39+
func (k *Kmp) AppendPatternStr(patternStr string) {
40+
start := len([]rune(k.pattern)) + 1
41+
k.pattern += patternStr
42+
k.buildNext(start)
43+
}
44+
45+
// ResetPatternStr 重置模式串
46+
func (k *Kmp) ResetPatternStr(patternStr string) {
47+
k.pattern = patternStr
48+
k.next = nil
49+
k.buildNext(0)
50+
}
51+
52+
// Search 返回所有 pattern 在 content 中出现的开始位置的 index
53+
func (k Kmp) Search(content string) (indexs []int) {
54+
rpattern, rcontent := []rune(k.pattern), []rune(content)
55+
n, m := len(rcontent), len(rpattern)
56+
if n == 0 || m == 0 {
57+
return nil
58+
}
59+
j := 0
60+
for i := 0; i < n; i++ {
61+
for ; j > 0 && rcontent[i] != rpattern[j]; j = k.next[j] {
62+
}
63+
if rcontent[i] == rpattern[j] {
64+
j++
65+
}
66+
if j == m {
67+
indexs = append(indexs, i-m+1)
68+
j = k.next[j]
69+
}
70+
}
71+
return indexs
72+
}

text_test.go

+21
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,24 @@ func TestSliceSmae(t *testing.T) {
3333
// test can not change order of a
3434
t.Log(a)
3535
}
36+
37+
func TestKmp(t *testing.T) {
38+
k := textalg.BuildKmp("a")
39+
indexs := k.Search("aaaaab") // find "a" in "aaaaab"
40+
t.Log(indexs)
41+
k.AppendPatternStr("a")
42+
indexs = k.Search("aaaaab") // find "aa" in "aaaaab"
43+
t.Log(indexs)
44+
k.AppendPatternStr("a")
45+
indexs = k.Search("aaaaab") // find "aaa" in "aaaaab"
46+
t.Log(indexs)
47+
k.AppendPatternStr("b")
48+
indexs = k.Search("aaaaab") // find "aaab" in "aaaaab"
49+
t.Log(indexs)
50+
k.AppendPatternStr("b")
51+
indexs = k.Search("aaaaab") // find "aaabb" in "aaaaab"
52+
t.Log(indexs)
53+
k.ResetPatternStr("ab")
54+
indexs = k.Search("aaaaab") // find "ab" in "aaaaab"
55+
t.Log(indexs)
56+
}

0 commit comments

Comments
 (0)