boyer_moore 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/boyer_moore.gemspec +2 -2
- data/lib/boyer_moore.rb +76 -84
- data/lib/boyer_moore/version.rb +1 -1
- data/test_file +1 -0
- metadata +12 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7de6b2a49229c15b9f3ab4a7311bcbd77789d02b
|
4
|
+
data.tar.gz: 21c26b9a7476405f08eaef5fc76f614496664850
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6199a53c8228caded86afe336064ee3f0ae98008fba3786861f38b021f184c369efcd0bb9528fe86b26c1f03790599806483be4c89129258d845ec269193da86
|
7
|
+
data.tar.gz: acadd4c9f7de76fdc4e25e3208403eba5704949d177eccb41ee7f02eda772421851f13b010192b44388b2486d6728b2036f982d3dfa608ea44f11d9f154978e4
|
data/boyer_moore.gemspec
CHANGED
@@ -26,6 +26,6 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
27
|
spec.require_paths = ["lib"]
|
28
28
|
|
29
|
-
spec.add_development_dependency "bundler"
|
30
|
-
spec.add_development_dependency "rake"
|
29
|
+
spec.add_development_dependency "bundler"
|
30
|
+
spec.add_development_dependency "rake"
|
31
31
|
end
|
data/lib/boyer_moore.rb
CHANGED
@@ -1,108 +1,100 @@
|
|
1
|
-
|
1
|
+
require_relative "./boyer_moore/version"
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
@regexps = {}
|
7
|
-
@regular = {}
|
8
|
-
end
|
3
|
+
module BoyerMoore
|
4
|
+
def self.search(haystack, needle_string)
|
5
|
+
needle = Needle.new(needle_string)
|
9
6
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
7
|
+
haystack_index = 0
|
8
|
+
while haystack_index <= haystack.size - needle.size
|
9
|
+
if skip_by = needle.match_or_skip_by(haystack, haystack_index)
|
10
|
+
haystack_index += skip_by
|
11
|
+
else
|
12
|
+
break haystack_index # Found a match at haystack_index!
|
16
13
|
end
|
17
14
|
end
|
18
|
-
nil
|
19
15
|
end
|
20
16
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
@regular[k] = v
|
17
|
+
class Needle
|
18
|
+
def initialize(needle)
|
19
|
+
needle.size > 0 or raise "Must pass needle with size > 0"
|
20
|
+
@needle = needle
|
26
21
|
end
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
30
22
|
|
31
|
-
|
23
|
+
def size
|
24
|
+
@needle.size
|
25
|
+
end
|
32
26
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
return haystack if needle_len == 0
|
38
|
-
badcharacter = self.prepare_badcharacter_heuristic(needle)
|
39
|
-
goodsuffix = self.prepare_goodsuffix_heuristic(needle)
|
40
|
-
s = 0
|
41
|
-
while s <= haystack_len - needle_len
|
42
|
-
j = needle_len
|
43
|
-
while (j > 0) && self.needle_matches?(needle[j-1], haystack[s+j-1])
|
44
|
-
j -= 1
|
27
|
+
def match_or_skip_by(haystack, haystack_index)
|
28
|
+
if mismatch_idx = mismatch_index(haystack, haystack_index)
|
29
|
+
mismatch_char_index = character_index(haystack[haystack_index + mismatch_idx])
|
30
|
+
skip_by(mismatch_char_index, mismatch_idx)
|
45
31
|
end
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
return s
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def mismatch_index(haystack, haystack_index)
|
37
|
+
compare_index = size - 1
|
38
|
+
while @needle[compare_index] == haystack[haystack_index + compare_index]
|
39
|
+
compare_index -= 1
|
40
|
+
compare_index < 0 and return nil
|
56
41
|
end
|
42
|
+
compare_index
|
57
43
|
end
|
58
|
-
return nil
|
59
|
-
end
|
60
44
|
|
61
|
-
|
62
|
-
|
63
|
-
0.upto(str.length - 1) do |i|
|
64
|
-
result[str[i]] = i
|
45
|
+
def character_index(char)
|
46
|
+
character_indexes[char] || -1
|
65
47
|
end
|
66
|
-
result
|
67
|
-
end
|
68
48
|
|
69
|
-
|
70
|
-
|
71
|
-
result = []
|
72
|
-
reversed = normal.dup.reverse
|
73
|
-
prefix_normal = compute_prefix(normal)
|
74
|
-
prefix_reversed = compute_prefix(reversed)
|
75
|
-
0.upto(size) do |i|
|
76
|
-
result[i] = size - prefix_normal[size-1]
|
49
|
+
def good_suffix(compare_index)
|
50
|
+
good_suffixes[compare_index]
|
77
51
|
end
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
52
|
+
|
53
|
+
def skip_by(mismatch_char_index, compare_index)
|
54
|
+
suffix_index = good_suffix(compare_index + 1)
|
55
|
+
if mismatch_char_index <= compare_index && (m = compare_index - mismatch_char_index) > suffix_index
|
56
|
+
m
|
57
|
+
else
|
58
|
+
suffix_index
|
59
|
+
end
|
82
60
|
end
|
83
|
-
result
|
84
|
-
end
|
85
61
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
62
|
+
def character_indexes
|
63
|
+
@char_indexes ||=
|
64
|
+
(0...@needle.length).reduce({}) do |hash, i|
|
65
|
+
hash[@needle[i]] = i
|
66
|
+
hash
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def good_suffixes
|
71
|
+
@good_suffixes ||=
|
72
|
+
begin
|
73
|
+
prefix_normal = self.class.prefix(@needle)
|
74
|
+
prefix_reversed = self.class.prefix(@needle.reverse)
|
75
|
+
result = []
|
76
|
+
(0..@needle.size).each do |i|
|
77
|
+
result[i] = @needle.size - prefix_normal[@needle.size-1]
|
78
|
+
end
|
79
|
+
(0...@needle.size).each do |i|
|
80
|
+
j = @needle.size - prefix_reversed[i]
|
81
|
+
k = i - prefix_reversed[i] + 1
|
82
|
+
result[j] > k and result[j] = k
|
83
|
+
end
|
84
|
+
result
|
85
|
+
end
|
91
86
|
end
|
92
|
-
end
|
93
87
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
k
|
88
|
+
def self.prefix(string)
|
89
|
+
k = 0
|
90
|
+
(1...string.length).reduce([0]) do |prefix, q|
|
91
|
+
while k > 0 && string[k] != string[q]
|
92
|
+
k = prefix[k - 1]
|
93
|
+
end
|
94
|
+
string[k] == string[q] and k += 1
|
95
|
+
prefix[q] = k
|
96
|
+
prefix
|
101
97
|
end
|
102
|
-
k += 1 if(str[k] == str[q])
|
103
|
-
result[q] = k
|
104
98
|
end
|
105
|
-
result
|
106
99
|
end
|
107
|
-
|
108
100
|
end
|
data/lib/boyer_moore/version.rb
CHANGED
data/test_file
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
123456
|
metadata
CHANGED
@@ -1,43 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: boyer_moore
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sri Harsha Kappala
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0'
|
41
41
|
description: Ruby wrapper for Boyer-Moore - The fastest search strategy, ever!
|
42
42
|
email:
|
43
43
|
- sriharsha.kappala@hotmail.com
|
@@ -55,6 +55,7 @@ files:
|
|
55
55
|
- boyer_moore.gemspec
|
56
56
|
- lib/boyer_moore.rb
|
57
57
|
- lib/boyer_moore/version.rb
|
58
|
+
- test_file
|
58
59
|
homepage: https://github.com/sriharshakappala/boyer_moore
|
59
60
|
licenses:
|
60
61
|
- MIT
|
@@ -76,7 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
76
77
|
version: '0'
|
77
78
|
requirements: []
|
78
79
|
rubyforge_project:
|
79
|
-
rubygems_version: 2.4
|
80
|
+
rubygems_version: 2.6.4
|
80
81
|
signing_key:
|
81
82
|
specification_version: 4
|
82
83
|
summary: Ruby wrapper for BoyerMoore algorithm - The fastest search strategy, ever!
|