ac-library-rb 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/unittest.yml +16 -0
- data/.gitignore +11 -0
- data/.rubocop.yml +198 -0
- data/Gemfile +3 -0
- data/LICENSE +116 -0
- data/README.ja.md +56 -0
- data/README.md +41 -0
- data/Rakefile +11 -0
- data/ac-library-rb.gemspec +32 -0
- data/bin/console +8 -0
- data/bin/lock_lib.rb +27 -0
- data/bin/setup +8 -0
- data/document_en/binary_index_tree.md +3 -0
- data/document_en/convolution.md +67 -0
- data/document_en/dsu.md +132 -0
- data/document_en/fenwick_tree.md +99 -0
- data/document_en/index.md +79 -0
- data/document_en/lazy_segtree.md +141 -0
- data/document_en/math.md +104 -0
- data/document_en/max_flow.md +165 -0
- data/document_en/min_cost_flow.md +132 -0
- data/document_en/modint.md +263 -0
- data/document_en/priority_queue.md +119 -0
- data/document_en/segtree.md +134 -0
- data/document_en/string.md +106 -0
- data/document_en/two_sat.md +91 -0
- data/document_en/union_find.md +3 -0
- data/document_ja/convolution.md +64 -0
- data/document_ja/dsu.md +183 -0
- data/document_ja/fenwick_tree.md +83 -0
- data/document_ja/index.md +89 -0
- data/document_ja/lazy_segtree.md +135 -0
- data/document_ja/math.md +116 -0
- data/document_ja/max_flow.md +129 -0
- data/document_ja/min_cost_flow.md +105 -0
- data/document_ja/modint.md +349 -0
- data/document_ja/priority_queue.md +103 -0
- data/document_ja/scc.md +65 -0
- data/document_ja/segtree.md +145 -0
- data/document_ja/string.md +105 -0
- data/document_ja/two_sat.md +87 -0
- data/lib/ac-library-rb/version.rb +3 -0
- data/lib/convolution.rb +124 -0
- data/lib/core_ext/modint.rb +19 -0
- data/lib/crt.rb +52 -0
- data/lib/dsu.rb +44 -0
- data/lib/fenwick_tree.rb +48 -0
- data/lib/floor_sum.rb +21 -0
- data/lib/inv_mod.rb +26 -0
- data/lib/lazy_segtree.rb +149 -0
- data/lib/lcp_array.rb +23 -0
- data/lib/max_flow.rb +137 -0
- data/lib/min_cost_flow.rb +143 -0
- data/lib/modint.rb +170 -0
- data/lib/pow_mod.rb +13 -0
- data/lib/priority_queue.rb +89 -0
- data/lib/scc.rb +77 -0
- data/lib/segtree.rb +140 -0
- data/lib/suffix_array.rb +128 -0
- data/lib/two_sat.rb +34 -0
- data/lib/z_algorithm.rb +32 -0
- data/lib_helpers/ac-library-rb/all.rb +22 -0
- data/lib_lock/ac-library-rb.rb +22 -0
- data/lib_lock/ac-library-rb/convolution.rb +126 -0
- data/lib_lock/ac-library-rb/core_ext/modint.rb +19 -0
- data/lib_lock/ac-library-rb/crt.rb +54 -0
- data/lib_lock/ac-library-rb/dsu.rb +46 -0
- data/lib_lock/ac-library-rb/fenwick_tree.rb +50 -0
- data/lib_lock/ac-library-rb/floor_sum.rb +23 -0
- data/lib_lock/ac-library-rb/inv_mod.rb +28 -0
- data/lib_lock/ac-library-rb/lazy_segtree.rb +151 -0
- data/lib_lock/ac-library-rb/lcp_array.rb +25 -0
- data/lib_lock/ac-library-rb/max_flow.rb +139 -0
- data/lib_lock/ac-library-rb/min_cost_flow.rb +145 -0
- data/lib_lock/ac-library-rb/modint.rb +172 -0
- data/lib_lock/ac-library-rb/pow_mod.rb +15 -0
- data/lib_lock/ac-library-rb/priority_queue.rb +91 -0
- data/lib_lock/ac-library-rb/scc.rb +79 -0
- data/lib_lock/ac-library-rb/segtree.rb +142 -0
- data/lib_lock/ac-library-rb/suffix_array.rb +130 -0
- data/lib_lock/ac-library-rb/two_sat.rb +36 -0
- data/lib_lock/ac-library-rb/z_algorithm.rb +34 -0
- metadata +158 -0
@@ -0,0 +1,130 @@
|
|
1
|
+
module AcLibraryRb
|
2
|
+
# induce sort (internal method)
|
3
|
+
def sa_is_induce(s, ls, sum_l, sum_s, lms)
|
4
|
+
n = s.size
|
5
|
+
sa = [-1] * n
|
6
|
+
|
7
|
+
buf = sum_s.dup
|
8
|
+
lms.each{ |lms|
|
9
|
+
if lms != n
|
10
|
+
sa[buf[s[lms]]] = lms
|
11
|
+
buf[s[lms]] += 1
|
12
|
+
end
|
13
|
+
}
|
14
|
+
|
15
|
+
buf = sum_l.dup
|
16
|
+
sa[buf[s[-1]]] = n - 1
|
17
|
+
buf[s[-1]] += 1
|
18
|
+
sa.each{ |v|
|
19
|
+
if v >= 1 && !ls[v - 1]
|
20
|
+
sa[buf[s[v - 1]]] = v - 1
|
21
|
+
buf[s[v - 1]] += 1
|
22
|
+
end
|
23
|
+
}
|
24
|
+
|
25
|
+
buf = sum_l.dup
|
26
|
+
sa.reverse_each{ |v|
|
27
|
+
if v >= 1 && ls[v - 1]
|
28
|
+
buf[s[v - 1] + 1] -= 1
|
29
|
+
sa[buf[s[v - 1] + 1]] = v - 1
|
30
|
+
end
|
31
|
+
}
|
32
|
+
|
33
|
+
return sa
|
34
|
+
end
|
35
|
+
|
36
|
+
# SA-IS (internal method)
|
37
|
+
def sa_is(s, upper)
|
38
|
+
n = s.size
|
39
|
+
|
40
|
+
return [] if n == 0
|
41
|
+
return [0] if n == 1
|
42
|
+
|
43
|
+
ls = [false] * n
|
44
|
+
(n - 2).downto(0){ |i|
|
45
|
+
ls[i] = (s[i] == s[i + 1] ? ls[i + 1] : s[i] < s[i + 1])
|
46
|
+
}
|
47
|
+
|
48
|
+
sum_l = [0] * (upper + 1)
|
49
|
+
sum_s = [0] * (upper + 1)
|
50
|
+
n.times{ |i|
|
51
|
+
if ls[i]
|
52
|
+
sum_l[s[i] + 1] += 1
|
53
|
+
else
|
54
|
+
sum_s[s[i]] += 1
|
55
|
+
end
|
56
|
+
}
|
57
|
+
0.upto(upper){ |i|
|
58
|
+
sum_s[i] += sum_l[i]
|
59
|
+
sum_l[i + 1] += sum_s[i] if i < upper
|
60
|
+
}
|
61
|
+
|
62
|
+
lms = (1 ... n).select{ |i| !ls[i - 1] && ls[i] }
|
63
|
+
m = lms.size
|
64
|
+
lms_map = [-1] * (n + 1)
|
65
|
+
lms.each_with_index{ |lms, id| lms_map[lms] = id }
|
66
|
+
|
67
|
+
sa = sa_is_induce(s, ls, sum_l, sum_s, lms)
|
68
|
+
|
69
|
+
return sa if m == 0
|
70
|
+
|
71
|
+
sorted_lms = sa.select{ |sa| lms_map[sa] != -1 }
|
72
|
+
rec_s = [0] * m
|
73
|
+
rec_upper = 0
|
74
|
+
rec_s[lms_map[sorted_lms[0]]] = 0
|
75
|
+
1.upto(m - 1) do |i|
|
76
|
+
l, r = sorted_lms[i - 1, 2]
|
77
|
+
end_l = lms[lms_map[l] + 1] || n
|
78
|
+
end_r = lms[lms_map[r] + 1] || n
|
79
|
+
same = true
|
80
|
+
if end_l - l != end_r - r
|
81
|
+
same = false
|
82
|
+
else
|
83
|
+
while l < end_l
|
84
|
+
break if s[l] != s[r]
|
85
|
+
|
86
|
+
l += 1
|
87
|
+
r += 1
|
88
|
+
end
|
89
|
+
same = false if l == n || s[l] != s[r]
|
90
|
+
end
|
91
|
+
rec_upper += 1 if not same
|
92
|
+
rec_s[lms_map[sorted_lms[i]]] = rec_upper
|
93
|
+
end
|
94
|
+
|
95
|
+
sa_is(rec_s, rec_upper).each_with_index{ |rec_sa, id|
|
96
|
+
sorted_lms[id] = lms[rec_sa]
|
97
|
+
}
|
98
|
+
|
99
|
+
return sa_is_induce(s, ls, sum_l, sum_s, sorted_lms)
|
100
|
+
end
|
101
|
+
|
102
|
+
# suffix array for array of integers or string
|
103
|
+
def suffix_array(s, upper = nil)
|
104
|
+
if not upper
|
105
|
+
case s
|
106
|
+
when Array
|
107
|
+
# compression
|
108
|
+
n = s.size
|
109
|
+
idx = (0 ... n).sort_by{ |i| s[i] }
|
110
|
+
t = [0] * n
|
111
|
+
upper = 0
|
112
|
+
t[idx[0]] = 0
|
113
|
+
1.upto(n - 1){ |i|
|
114
|
+
upper += 1 if s[idx[i - 1]] != s[idx[i]]
|
115
|
+
t[idx[i]] = upper
|
116
|
+
}
|
117
|
+
s = t
|
118
|
+
when String
|
119
|
+
upper = 255
|
120
|
+
s = s.bytes
|
121
|
+
end
|
122
|
+
else
|
123
|
+
s.each{ |s|
|
124
|
+
raise ArgumentError if s < 0 || upper < s
|
125
|
+
}
|
126
|
+
end
|
127
|
+
|
128
|
+
return sa_is(s, upper)
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module AcLibraryRb
|
2
|
+
require_relative './scc.rb'
|
3
|
+
|
4
|
+
# TwoSAT
|
5
|
+
# Reference: https://github.com/atcoder/ac-library/blob/master/atcoder/twosat.hpp
|
6
|
+
class TwoSAT
|
7
|
+
def initialize(n = 0)
|
8
|
+
@n = n
|
9
|
+
@answer = Array.new(n)
|
10
|
+
@scc = SCCGraph.new(2 * n)
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :answer
|
14
|
+
|
15
|
+
def add_clause(i, f, j, g)
|
16
|
+
raise RangeError unless (0...@n).cover?(i) && (0...@n).cover?(j)
|
17
|
+
|
18
|
+
@scc.add_edge(2 * i + (f ? 0 : 1), 2 * j + (g ? 1 : 0))
|
19
|
+
@scc.add_edge(2 * j + (g ? 0 : 1), 2 * i + (f ? 1 : 0))
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def satisfiable
|
24
|
+
id = @scc.send(:scc_ids)[1]
|
25
|
+
@n.times do |i|
|
26
|
+
return false if id[2 * i] == id[2 * i + 1]
|
27
|
+
|
28
|
+
@answer[i] = id[2 * i] < id[2 * i + 1]
|
29
|
+
end
|
30
|
+
true
|
31
|
+
end
|
32
|
+
alias satisfiable? satisfiable
|
33
|
+
end
|
34
|
+
|
35
|
+
TwoSat = TwoSAT
|
36
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module AcLibraryRb
|
2
|
+
# this implementation is different from ACL because of calculation time
|
3
|
+
# ref : https://snuke.hatenablog.com/entry/2014/12/03/214243
|
4
|
+
# ACL implementation : https://atcoder.jp/contests/abc135/submissions/18836384 (731ms)
|
5
|
+
# this implementation : https://atcoder.jp/contests/abc135/submissions/18836378 (525ms)
|
6
|
+
|
7
|
+
def z_algorithm(s)
|
8
|
+
n = s.size
|
9
|
+
return [] if n == 0
|
10
|
+
|
11
|
+
s = s.codepoints if s.is_a?(String)
|
12
|
+
|
13
|
+
z = [0] * n
|
14
|
+
z[0] = n
|
15
|
+
i, j = 1, 0
|
16
|
+
while i < n
|
17
|
+
j += 1 while i + j < n && s[j] == s[i + j]
|
18
|
+
z[i] = j
|
19
|
+
if j == 0
|
20
|
+
i += 1
|
21
|
+
next
|
22
|
+
end
|
23
|
+
k = 1
|
24
|
+
while i + k < n && k + z[k] < j
|
25
|
+
z[i + k] = z[k]
|
26
|
+
k += 1
|
27
|
+
end
|
28
|
+
i += k
|
29
|
+
j -= k
|
30
|
+
end
|
31
|
+
|
32
|
+
return z
|
33
|
+
end
|
34
|
+
end
|
metadata
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ac-library-rb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- universato
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-05-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: minitest
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: |-
|
42
|
+
ac-library-rb is a ruby port of AtCoder Library (ACL).
|
43
|
+
DSU(UnionFind), FenwickTree, PriorityQueue, Segtree, SCC, 2-SAT, suffix_array, lcp_array, z_algorithm, crt, inv_mod, floor_sum, max_flow, min_cost_flow......
|
44
|
+
email:
|
45
|
+
- universato@gmail.com
|
46
|
+
executables: []
|
47
|
+
extensions: []
|
48
|
+
extra_rdoc_files: []
|
49
|
+
files:
|
50
|
+
- ".github/workflows/unittest.yml"
|
51
|
+
- ".gitignore"
|
52
|
+
- ".rubocop.yml"
|
53
|
+
- Gemfile
|
54
|
+
- LICENSE
|
55
|
+
- README.ja.md
|
56
|
+
- README.md
|
57
|
+
- Rakefile
|
58
|
+
- ac-library-rb.gemspec
|
59
|
+
- bin/console
|
60
|
+
- bin/lock_lib.rb
|
61
|
+
- bin/setup
|
62
|
+
- document_en/binary_index_tree.md
|
63
|
+
- document_en/convolution.md
|
64
|
+
- document_en/dsu.md
|
65
|
+
- document_en/fenwick_tree.md
|
66
|
+
- document_en/index.md
|
67
|
+
- document_en/lazy_segtree.md
|
68
|
+
- document_en/math.md
|
69
|
+
- document_en/max_flow.md
|
70
|
+
- document_en/min_cost_flow.md
|
71
|
+
- document_en/modint.md
|
72
|
+
- document_en/priority_queue.md
|
73
|
+
- document_en/segtree.md
|
74
|
+
- document_en/string.md
|
75
|
+
- document_en/two_sat.md
|
76
|
+
- document_en/union_find.md
|
77
|
+
- document_ja/convolution.md
|
78
|
+
- document_ja/dsu.md
|
79
|
+
- document_ja/fenwick_tree.md
|
80
|
+
- document_ja/index.md
|
81
|
+
- document_ja/lazy_segtree.md
|
82
|
+
- document_ja/math.md
|
83
|
+
- document_ja/max_flow.md
|
84
|
+
- document_ja/min_cost_flow.md
|
85
|
+
- document_ja/modint.md
|
86
|
+
- document_ja/priority_queue.md
|
87
|
+
- document_ja/scc.md
|
88
|
+
- document_ja/segtree.md
|
89
|
+
- document_ja/string.md
|
90
|
+
- document_ja/two_sat.md
|
91
|
+
- lib/ac-library-rb/version.rb
|
92
|
+
- lib/convolution.rb
|
93
|
+
- lib/core_ext/modint.rb
|
94
|
+
- lib/crt.rb
|
95
|
+
- lib/dsu.rb
|
96
|
+
- lib/fenwick_tree.rb
|
97
|
+
- lib/floor_sum.rb
|
98
|
+
- lib/inv_mod.rb
|
99
|
+
- lib/lazy_segtree.rb
|
100
|
+
- lib/lcp_array.rb
|
101
|
+
- lib/max_flow.rb
|
102
|
+
- lib/min_cost_flow.rb
|
103
|
+
- lib/modint.rb
|
104
|
+
- lib/pow_mod.rb
|
105
|
+
- lib/priority_queue.rb
|
106
|
+
- lib/scc.rb
|
107
|
+
- lib/segtree.rb
|
108
|
+
- lib/suffix_array.rb
|
109
|
+
- lib/two_sat.rb
|
110
|
+
- lib/z_algorithm.rb
|
111
|
+
- lib_helpers/ac-library-rb/all.rb
|
112
|
+
- lib_lock/ac-library-rb.rb
|
113
|
+
- lib_lock/ac-library-rb/convolution.rb
|
114
|
+
- lib_lock/ac-library-rb/core_ext/modint.rb
|
115
|
+
- lib_lock/ac-library-rb/crt.rb
|
116
|
+
- lib_lock/ac-library-rb/dsu.rb
|
117
|
+
- lib_lock/ac-library-rb/fenwick_tree.rb
|
118
|
+
- lib_lock/ac-library-rb/floor_sum.rb
|
119
|
+
- lib_lock/ac-library-rb/inv_mod.rb
|
120
|
+
- lib_lock/ac-library-rb/lazy_segtree.rb
|
121
|
+
- lib_lock/ac-library-rb/lcp_array.rb
|
122
|
+
- lib_lock/ac-library-rb/max_flow.rb
|
123
|
+
- lib_lock/ac-library-rb/min_cost_flow.rb
|
124
|
+
- lib_lock/ac-library-rb/modint.rb
|
125
|
+
- lib_lock/ac-library-rb/pow_mod.rb
|
126
|
+
- lib_lock/ac-library-rb/priority_queue.rb
|
127
|
+
- lib_lock/ac-library-rb/scc.rb
|
128
|
+
- lib_lock/ac-library-rb/segtree.rb
|
129
|
+
- lib_lock/ac-library-rb/suffix_array.rb
|
130
|
+
- lib_lock/ac-library-rb/two_sat.rb
|
131
|
+
- lib_lock/ac-library-rb/z_algorithm.rb
|
132
|
+
homepage: https://github.com/universato/ac-library-rb
|
133
|
+
licenses:
|
134
|
+
- CC0
|
135
|
+
metadata:
|
136
|
+
homepage_uri: https://github.com/universato/ac-library-rb
|
137
|
+
source_code_uri: https://github.com/universato/ac-library-rb
|
138
|
+
post_install_message:
|
139
|
+
rdoc_options: []
|
140
|
+
require_paths:
|
141
|
+
- lib_lock
|
142
|
+
- lib_helpers
|
143
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: 2.3.0
|
148
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
requirements: []
|
154
|
+
rubygems_version: 3.2.11
|
155
|
+
signing_key:
|
156
|
+
specification_version: 4
|
157
|
+
summary: ac-library-rb is a ruby port of AtCoder Library (ACL).
|
158
|
+
test_files: []
|