File tree 2 files changed +93
-0
lines changed
2 files changed +93
-0
lines changed Original file line number Diff line number Diff line change
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
+ }
Original file line number Diff line number Diff line change @@ -33,3 +33,24 @@ func TestSliceSmae(t *testing.T) {
33
33
// test can not change order of a
34
34
t .Log (a )
35
35
}
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
+ }
You can’t perform that action at this time.
0 commit comments