ac-library-rb 0.5.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.
Files changed (84) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/unittest.yml +16 -0
  3. data/.gitignore +11 -0
  4. data/.rubocop.yml +198 -0
  5. data/Gemfile +3 -0
  6. data/LICENSE +116 -0
  7. data/README.ja.md +56 -0
  8. data/README.md +41 -0
  9. data/Rakefile +11 -0
  10. data/ac-library-rb.gemspec +32 -0
  11. data/bin/console +8 -0
  12. data/bin/lock_lib.rb +27 -0
  13. data/bin/setup +8 -0
  14. data/document_en/binary_index_tree.md +3 -0
  15. data/document_en/convolution.md +67 -0
  16. data/document_en/dsu.md +132 -0
  17. data/document_en/fenwick_tree.md +99 -0
  18. data/document_en/index.md +79 -0
  19. data/document_en/lazy_segtree.md +141 -0
  20. data/document_en/math.md +104 -0
  21. data/document_en/max_flow.md +165 -0
  22. data/document_en/min_cost_flow.md +132 -0
  23. data/document_en/modint.md +263 -0
  24. data/document_en/priority_queue.md +119 -0
  25. data/document_en/segtree.md +134 -0
  26. data/document_en/string.md +106 -0
  27. data/document_en/two_sat.md +91 -0
  28. data/document_en/union_find.md +3 -0
  29. data/document_ja/convolution.md +64 -0
  30. data/document_ja/dsu.md +183 -0
  31. data/document_ja/fenwick_tree.md +83 -0
  32. data/document_ja/index.md +89 -0
  33. data/document_ja/lazy_segtree.md +135 -0
  34. data/document_ja/math.md +116 -0
  35. data/document_ja/max_flow.md +129 -0
  36. data/document_ja/min_cost_flow.md +105 -0
  37. data/document_ja/modint.md +349 -0
  38. data/document_ja/priority_queue.md +103 -0
  39. data/document_ja/scc.md +65 -0
  40. data/document_ja/segtree.md +145 -0
  41. data/document_ja/string.md +105 -0
  42. data/document_ja/two_sat.md +87 -0
  43. data/lib/ac-library-rb/version.rb +3 -0
  44. data/lib/convolution.rb +124 -0
  45. data/lib/core_ext/modint.rb +19 -0
  46. data/lib/crt.rb +52 -0
  47. data/lib/dsu.rb +44 -0
  48. data/lib/fenwick_tree.rb +48 -0
  49. data/lib/floor_sum.rb +21 -0
  50. data/lib/inv_mod.rb +26 -0
  51. data/lib/lazy_segtree.rb +149 -0
  52. data/lib/lcp_array.rb +23 -0
  53. data/lib/max_flow.rb +137 -0
  54. data/lib/min_cost_flow.rb +143 -0
  55. data/lib/modint.rb +170 -0
  56. data/lib/pow_mod.rb +13 -0
  57. data/lib/priority_queue.rb +89 -0
  58. data/lib/scc.rb +77 -0
  59. data/lib/segtree.rb +140 -0
  60. data/lib/suffix_array.rb +128 -0
  61. data/lib/two_sat.rb +34 -0
  62. data/lib/z_algorithm.rb +32 -0
  63. data/lib_helpers/ac-library-rb/all.rb +22 -0
  64. data/lib_lock/ac-library-rb.rb +22 -0
  65. data/lib_lock/ac-library-rb/convolution.rb +126 -0
  66. data/lib_lock/ac-library-rb/core_ext/modint.rb +19 -0
  67. data/lib_lock/ac-library-rb/crt.rb +54 -0
  68. data/lib_lock/ac-library-rb/dsu.rb +46 -0
  69. data/lib_lock/ac-library-rb/fenwick_tree.rb +50 -0
  70. data/lib_lock/ac-library-rb/floor_sum.rb +23 -0
  71. data/lib_lock/ac-library-rb/inv_mod.rb +28 -0
  72. data/lib_lock/ac-library-rb/lazy_segtree.rb +151 -0
  73. data/lib_lock/ac-library-rb/lcp_array.rb +25 -0
  74. data/lib_lock/ac-library-rb/max_flow.rb +139 -0
  75. data/lib_lock/ac-library-rb/min_cost_flow.rb +145 -0
  76. data/lib_lock/ac-library-rb/modint.rb +172 -0
  77. data/lib_lock/ac-library-rb/pow_mod.rb +15 -0
  78. data/lib_lock/ac-library-rb/priority_queue.rb +91 -0
  79. data/lib_lock/ac-library-rb/scc.rb +79 -0
  80. data/lib_lock/ac-library-rb/segtree.rb +142 -0
  81. data/lib_lock/ac-library-rb/suffix_array.rb +130 -0
  82. data/lib_lock/ac-library-rb/two_sat.rb +36 -0
  83. data/lib_lock/ac-library-rb/z_algorithm.rb +34 -0
  84. metadata +158 -0
data/lib/lcp_array.rb ADDED
@@ -0,0 +1,23 @@
1
+ # lcp array for array of integers or string
2
+ def lcp_array(s, sa)
3
+ s = s.bytes if s.is_a?(String)
4
+
5
+ n = s.size
6
+ rnk = [0] * n
7
+ sa.each_with_index{ |sa, id|
8
+ rnk[sa] = id
9
+ }
10
+
11
+ lcp = [0] * (n - 1)
12
+ h = 0
13
+ n.times{ |i|
14
+ h -= 1 if h > 0
15
+ next if rnk[i] == 0
16
+
17
+ j = sa[rnk[i] - 1]
18
+ h += 1 while j + h < n && i + h < n && s[j + h] == s[i + h]
19
+ lcp[rnk[i] - 1] = h
20
+ }
21
+
22
+ return lcp
23
+ end
data/lib/max_flow.rb ADDED
@@ -0,0 +1,137 @@
1
+ # MaxFlowGraph
2
+ class MaxFlow
3
+ def initialize(n = 0)
4
+ @n = n
5
+ @pos = []
6
+ @g = Array.new(n) { [] }
7
+ end
8
+
9
+ def add_edge(from, to, cap)
10
+ edge_number = @pos.size
11
+
12
+ @pos << [from, @g[from].size]
13
+
14
+ from_id = @g[from].size
15
+ to_id = @g[to].size
16
+ to_id += 1 if from == to
17
+ @g[from] << [to, to_id, cap]
18
+ @g[to] << [from, from_id, 0]
19
+
20
+ edge_number
21
+ end
22
+
23
+ def push(edge)
24
+ add_edge(*edge)
25
+ end
26
+ alias << push
27
+
28
+ # return edge = [from, to, cap, flow]
29
+ def [](i)
30
+ _e = @g[@pos[i][0]][@pos[i][1]]
31
+ _re = @g[_e[0]][_e[1]]
32
+ [@pos[i][0], _e[0], _e[-1] + _re[-1], _re[-1]]
33
+ end
34
+ alias get_edge []
35
+ alias edge []
36
+
37
+ def edges
38
+ @pos.map do |(from, id)|
39
+ _e = @g[from][id]
40
+ _re = @g[_e[0]][_e[1]]
41
+ [from, _e[0], _e[-1] + _re[-1], _re[-1]]
42
+ end
43
+ end
44
+
45
+ def change_edge(i, new_cap, new_flow)
46
+ _e = @g[@pos[i][0]][@pos[i][1]]
47
+ _re = @g[_e[0]][_e[1]]
48
+ _e[2] = new_cap - new_flow
49
+ _re[2] = new_flow
50
+ end
51
+
52
+ def flow(s, t, flow_limit = 1 << 64)
53
+ level = Array.new(@n)
54
+ iter = Array.new(@n)
55
+ que = []
56
+
57
+ flow = 0
58
+ while flow < flow_limit
59
+ bfs(s, t, level, que)
60
+ break if level[t] == -1
61
+
62
+ iter.fill(0)
63
+ while flow < flow_limit
64
+ f = dfs(t, flow_limit - flow, s, level, iter)
65
+ break if f == 0
66
+
67
+ flow += f
68
+ end
69
+ end
70
+
71
+ flow
72
+ end
73
+ alias max_flow flow
74
+
75
+ def min_cut(s)
76
+ visited = Array.new(@n, false)
77
+ que = [s]
78
+ while (q = que.shift)
79
+ visited[q] = true
80
+ @g[q].each do |(to, _rev, cap)|
81
+ if cap > 0 && !visited[to]
82
+ visited[to] = true
83
+ que << to
84
+ end
85
+ end
86
+ end
87
+ visited
88
+ end
89
+
90
+ private
91
+
92
+ def bfs(s, t, level, que)
93
+ level.fill(-1)
94
+ level[s] = 0
95
+ que.clear
96
+ que << s
97
+
98
+ while (v = que.shift)
99
+ @g[v].each do |e|
100
+ next if e[2] == 0 || level[e[0]] >= 0
101
+
102
+ level[e[0]] = level[v] + 1
103
+ return nil if e[0] == t
104
+
105
+ que << e[0]
106
+ end
107
+ end
108
+ end
109
+
110
+ def dfs(v, up, s, level, iter)
111
+ return up if v == s
112
+
113
+ res = 0
114
+ level_v = level[v]
115
+
116
+ while iter[v] < @g[v].size
117
+ i = iter[v]
118
+ e = @g[v][i]
119
+ cap = @g[e[0]][e[1]][2]
120
+ if level_v > level[e[0]] && cap > 0
121
+ d = dfs(e[0], (up - res < cap ? up - res : cap), s, level, iter)
122
+ if d > 0
123
+ @g[v][i][2] += d
124
+ @g[e[0]][e[1]][2] -= d
125
+ res += d
126
+ break if res == up
127
+ end
128
+ end
129
+ iter[v] += 1
130
+ end
131
+
132
+ res
133
+ end
134
+ end
135
+
136
+ MaxFlowGraph = MaxFlow
137
+ MFGraph = MaxFlow
@@ -0,0 +1,143 @@
1
+ require_relative './priority_queue.rb'
2
+
3
+ # Min Cost Flow Grapsh
4
+ class MinCostFlow
5
+ def initialize(n)
6
+ @n = n
7
+ @pos = []
8
+ @g_to = Array.new(n) { [] }
9
+ @g_rev = Array.new(n) { [] }
10
+ @g_cap = Array.new(n) { [] }
11
+ @g_cost = Array.new(n) { [] }
12
+ @pv = Array.new(n)
13
+ @pe = Array.new(n)
14
+ @dual = Array.new(n) { 0 }
15
+ end
16
+
17
+ def add_edge(from, to, cap, cost)
18
+ edge_number = @pos.size
19
+
20
+ @pos << [from, @g_to[from].size]
21
+
22
+ from_id = @g_to[from].size
23
+ to_id = @g_to[to].size
24
+ to_id += 1 if from == to
25
+
26
+ @g_to[from] << to
27
+ @g_rev[from] << to_id
28
+ @g_cap[from] << cap
29
+ @g_cost[from] << cost
30
+
31
+ @g_to[to] << from
32
+ @g_rev[to] << from_id
33
+ @g_cap[to] << 0
34
+ @g_cost[to] << -cost
35
+
36
+ edge_number
37
+ end
38
+
39
+ def get_edge(i)
40
+ from, id = @pos[i]
41
+ to = @g_to[from][id]
42
+ rid = @g_rev[from][id]
43
+ [from, to, @g_cap[from][id] + @g_cap[to][rid], @g_cap[to][rid], @g_cost[from][id]]
44
+ end
45
+ alias edge get_edge
46
+ alias [] get_edge
47
+
48
+ def edges
49
+ @pos.map do |(from, id)|
50
+ to = @g_to[from][id]
51
+ rid = @g_rev[from][id]
52
+ [from, to, @g_cap[from][id] + @g_cap[to][rid], @g_cap[to][rid], @g_cost[from][id]]
53
+ end
54
+ end
55
+
56
+ def flow(s, t, flow_limit = Float::MAX)
57
+ slope(s, t, flow_limit).last
58
+ end
59
+ alias min_cost_max_flow flow
60
+
61
+ def dual_ref(s, t)
62
+ dist = Array.new(@n, Float::MAX)
63
+ @pv.fill(-1)
64
+ @pe.fill(-1)
65
+ vis = Array.new(@n, false)
66
+
67
+ que = PriorityQueue.new { |par, chi| par[0] < chi[0] }
68
+ dist[s] = 0
69
+ que.push([0, s])
70
+
71
+ while (v = que.pop)
72
+ v = v[1]
73
+
74
+ next if vis[v]
75
+
76
+ vis[v] = true
77
+ break if v == t
78
+
79
+ @g_to[v].size.times do |i|
80
+ to = @g_to[v][i]
81
+ next if vis[to] || @g_cap[v][i] == 0
82
+
83
+ cost = @g_cost[v][i] - @dual[to] + @dual[v]
84
+ next unless dist[to] - dist[v] > cost
85
+
86
+ dist[to] = dist[v] + cost
87
+ @pv[to] = v
88
+ @pe[to] = i
89
+ que.push([dist[to], to])
90
+ end
91
+ end
92
+
93
+ return false unless vis[t]
94
+
95
+ @n.times do |i|
96
+ next unless vis[i]
97
+
98
+ @dual[i] -= dist[t] - dist[i]
99
+ end
100
+
101
+ true
102
+ end
103
+
104
+ def slope(s, t, flow_limit = Float::MAX)
105
+ flow = 0
106
+ cost = 0
107
+ prev_cost = -1
108
+ result = [[flow, cost]]
109
+
110
+ while flow < flow_limit
111
+ break unless dual_ref(s, t)
112
+
113
+ c = flow_limit - flow
114
+ v = t
115
+ while v != s
116
+ c = @g_cap[@pv[v]][@pe[v]] if c > @g_cap[@pv[v]][@pe[v]]
117
+ v = @pv[v]
118
+ end
119
+
120
+ v = t
121
+ while v != s
122
+ nv = @pv[v]
123
+ id = @pe[v]
124
+ @g_cap[nv][id] -= c
125
+ @g_cap[v][@g_rev[nv][id]] += c
126
+ v = nv
127
+ end
128
+
129
+ d = -@dual[s]
130
+ flow += c
131
+ cost += c * d
132
+ result.pop if prev_cost == d
133
+ result << [flow, cost]
134
+ prev_cost = d
135
+ end
136
+
137
+ result
138
+ end
139
+ alias min_cost_slop slope
140
+ end
141
+
142
+ MCF = MinCostFlow
143
+ MCFGraph = MinCostFlow
data/lib/modint.rb ADDED
@@ -0,0 +1,170 @@
1
+ require_relative './core_ext/modint.rb'
2
+
3
+ # ModInt
4
+ class ModInt < Numeric
5
+ class << self
6
+ def set_mod(mod)
7
+ raise ArgumentError unless mod.is_a? Integer and 1 <= mod
8
+
9
+ $_mod = mod
10
+ $_mod_is_prime = ModInt.prime?(mod)
11
+ end
12
+
13
+ def mod=(mod)
14
+ set_mod mod
15
+ end
16
+
17
+ def mod
18
+ $_mod
19
+ end
20
+
21
+ def raw(val)
22
+ x = allocate
23
+ x.val = val.to_i
24
+ x
25
+ end
26
+
27
+ def prime?(n)
28
+ return false if n <= 1
29
+ return true if n == 2 or n == 7 or n == 61
30
+ return false if (n & 1) == 0
31
+
32
+ d = n - 1
33
+ d >>= 1 while (d & 1) == 0
34
+ [2, 7, 61].each do |a|
35
+ t = d
36
+ y = a.pow(t, n)
37
+ while t != n - 1 and y != 1 and y != n - 1
38
+ y = y * y % n
39
+ t <<= 1
40
+ end
41
+ return false if y != n - 1 and (t & 1) == 0
42
+ end
43
+ true
44
+ end
45
+
46
+ def inv_gcd(a, b)
47
+ a %= b
48
+ return [b, 0] if a == 0
49
+
50
+ s, t = b, a
51
+ m0, m1 = 0, 1
52
+ while t != 0
53
+ u = s / t
54
+ s -= t * u
55
+ m0 -= m1 * u
56
+ s, t = t, s
57
+ m0, m1 = m1, m0
58
+ end
59
+ m0 += b / s if m0 < 0
60
+ [s, m0]
61
+ end
62
+ end
63
+
64
+ attr_accessor :val
65
+
66
+ alias to_i val
67
+
68
+ def initialize(val = 0)
69
+ @val = val.to_i % $_mod
70
+ end
71
+
72
+ def inc!
73
+ @val += 1
74
+ @val = 0 if @val == $_mod
75
+ self
76
+ end
77
+
78
+ def dec!
79
+ @val = $_mod if @val == 0
80
+ @val -= 1
81
+ self
82
+ end
83
+
84
+ def add!(other)
85
+ @val = (@val + other.to_i) % $_mod
86
+ self
87
+ end
88
+
89
+ def sub!(other)
90
+ @val = (@val - other.to_i) % $_mod
91
+ self
92
+ end
93
+
94
+ def mul!(other)
95
+ @val = @val * other.to_i % $_mod
96
+ self
97
+ end
98
+
99
+ def div!(other)
100
+ mul! inv_internal(other.to_i)
101
+ end
102
+
103
+ def +@
104
+ self
105
+ end
106
+
107
+ def -@
108
+ ModInt.raw($_mod - @val)
109
+ end
110
+
111
+ def **(other)
112
+ $_mod == 1 ? 0 : ModInt.raw(@val.pow(other, $_mod))
113
+ end
114
+ alias pow **
115
+
116
+ def inv
117
+ ModInt.raw(inv_internal(@val) % $_mod)
118
+ end
119
+
120
+ def coerce(other)
121
+ [ModInt(other), self]
122
+ end
123
+
124
+ def +(other)
125
+ dup.add! other
126
+ end
127
+
128
+ def -(other)
129
+ dup.sub! other
130
+ end
131
+
132
+ def *(other)
133
+ dup.mul! other
134
+ end
135
+
136
+ def /(other)
137
+ dup.div! other
138
+ end
139
+
140
+ def ==(other)
141
+ @val == other.to_i
142
+ end
143
+
144
+ def dup
145
+ ModInt.raw(@val)
146
+ end
147
+
148
+ def to_int
149
+ @val
150
+ end
151
+
152
+ def to_s
153
+ @val.to_s
154
+ end
155
+
156
+ def inspect
157
+ "#{@val} mod #{$_mod}"
158
+ end
159
+
160
+ private
161
+
162
+ def inv_internal(a)
163
+ if $_mod_is_prime
164
+ a != 0 ? a.pow($_mod - 2, $_mod) : raise(RangeError, 'no inverse')
165
+ else
166
+ g, x = ModInt.inv_gcd(a, $_mod)
167
+ g == 1 ? x : raise(RangeError, 'no inverse')
168
+ end
169
+ end
170
+ end