File tree Expand file tree Collapse file tree 2 files changed +93
-0
lines changed Expand file tree Collapse file tree 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) {
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+ }
You can’t perform that action at this time.
0 commit comments