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
@@ -0,0 +1,106 @@
1
+ # String
2
+
3
+ The substring of the `a`-th to `b-1`-th element of the string `s` is written as `s[a..b)`.
4
+
5
+
6
+ ## suffix_array
7
+
8
+ ```ruby
9
+ (1) suffix_array(s)
10
+ (2) suffix_array(a)
11
+ (3) suffix_array(a, upper)
12
+ ```
13
+ For a string `s` of length `n`, returns an array of `Integer` of length `n` as a Suffix Array.
14
+
15
+ Suffix Array `sa` is a permutation of `0 ... ... n`, and for each `i`, it is a permutation of `s[sa[i]. .n) < s[sa[i+1]. .n)` is satisfied.
16
+
17
+ This concept of Suffix Array can also be applied to general columns and works for `a`, an array of elements comparable with `<=>` operator. 1.
18
+
19
+ ### 1. `suffix_array(s)`
20
+
21
+ Convert internally to a sequence of bytes by `s.bytes`.
22
+
23
+ **Constraints**
24
+
25
+ - `s` is a string consisting only of characters with character code 255 or less.
26
+
27
+ **Complexity**
28
+
29
+ - `O(|s|)`
30
+
31
+ ### 2. `suffix_array(a)`
32
+
33
+ Inside, so-called coordinate compression is performed. Elements are converted to non-negative integers keeping their size relation.
34
+
35
+ **Constraints**
36
+
37
+ - The elements of `a` are comparable to each other with the `<=>` operator.
38
+
39
+ **Complexity**
40
+
41
+ - Assuming elements can be compared in constant time, `O(|a| log |a|)`
42
+
43
+ ### 3. `suffix_array(a, upper)`
44
+
45
+ **Constraints**
46
+
47
+ - `a` is an array of `Integer`.
48
+
49
+ - For all elements `x` of `a`, `0 ≤ x ≤ upper`.
50
+
51
+ **Complexity**
52
+
53
+ - `O(|a| + upper)`
54
+
55
+ ## lcp_array
56
+
57
+ ```ruby
58
+ lcp_array(s, sa)
59
+ ```
60
+
61
+ It returns an array of `Integer` of length `n-1` as an LCP Array of length `n` for strings `s`. The `i` th element is the length of LCP ( Longest Common Prefix ) for `s[sa[i]. .n)` and `s[sa[i+1]. .n)`.
62
+
63
+ This also works for general columns as well as `suffix_array`.
64
+
65
+ **Constraints**
66
+
67
+ - `sa` is a Suffix Array of `s`.
68
+
69
+ - If `s` is a string, `s` consists only of characters with character code 255 or less.
70
+
71
+ **Complexity**
72
+
73
+ - `O(|s|)`
74
+
75
+ ## z_algorithm
76
+
77
+ ```ruby
78
+ z_algorithm(s)
79
+ ```
80
+
81
+ It returns an array of `Integer` of length `n`, where `n` is the length of the input array. The `i` th element is the length of LCP ( Longest Common Prefix ) of `s[0..n)` and `s[i..n)`.
82
+
83
+ **Constraints**
84
+
85
+ - The elements of `s` can be compared with each other with the `==` operator
86
+
87
+
88
+ **Complexity**
89
+
90
+ - `O(|s|)`
91
+
92
+ <hr>
93
+
94
+ ## Verified
95
+
96
+ - suffix_array, lcp_array
97
+ - [I - Number of Substrings](https://atcoder.jp/contests/practice2/tasks/practice2_i)
98
+ - [AC 1362 ms](https://atcoder.jp/contests/practice2/submissions/17194669)
99
+ - z_algorithm
100
+ - [ABC135 F - Strings of Eternity](https://atcoder.jp/contests/abc135/tasks/abc135_f)
101
+ - [AC 1076 ms](https://atcoder.jp/contests/abc135/submissions/16656965)
102
+
103
+ ## Links
104
+
105
+ - AtCoder Library
106
+ - [Document String(HTML)](https://atcoder.github.io/ac-library/master/document_ja/string.html)
@@ -0,0 +1,91 @@
1
+ # 2-SAT
2
+
3
+ It solves 2-SAT.
4
+
5
+ For variables x_0, x_1, ..., x_N-1 and clauses with form
6
+
7
+ (x_i = f) ∨ (x_j = g)
8
+
9
+ it decides whether there is a truth assignment that satisfies all clauses.
10
+
11
+
12
+ **Alias**
13
+
14
+ `TwoSAT`, `TwoSat`
15
+
16
+ <hr>
17
+
18
+ ## Class Methods
19
+
20
+ ### new(n = 0) -> TwoSAT
21
+
22
+ ```ruby
23
+ ts = TwoSAT.new(n)
24
+ ```
25
+
26
+ It creates a 2-SAT of `n` variables and `0` clauses.
27
+
28
+ **Complexity**
29
+
30
+ O(n)
31
+
32
+ <hr>
33
+
34
+ ## Instance Methods
35
+
36
+ ### add_clause(i, f, j, g) -> nil
37
+
38
+ `i: Integer`, `f: bool`, `j: Integer`, `g: bool`
39
+
40
+ ```ruby
41
+ ts.add_clause(i, true, j, false)
42
+ ```
43
+
44
+ It adds a clause (x_i = f) ∨ (x_j = g).
45
+
46
+ **Constraints**
47
+
48
+ - `0 <= i < n`
49
+ - `0 <= j < n`
50
+
51
+ **Complexity**
52
+
53
+ - `O(1)` amortized
54
+
55
+ ### satisfiable? -> bool
56
+
57
+ ```ruby
58
+ ts.satisfiable?
59
+ ```
60
+
61
+ If there is a truth assignment that satisfies all clauses, it returns `true`. Otherwise, it returns `false`.
62
+
63
+ **Alias**
64
+
65
+ `satisfiable?`, `satisfiable`
66
+
67
+ **Complexity**
68
+
69
+ `O(n + m)`, where `m` is the number of added clauses.
70
+
71
+ ### answer -> Array(bool)
72
+
73
+ ```ruby
74
+ ts.answer
75
+ ```
76
+
77
+ It returns a truth assignment that `satisfie` all clauses of the last call of satisfiable. If we call it before calling `satisfiable` or when the last call of `satisfiable` returns `false`, it returns the vector of length `n` with undefined elements.
78
+
79
+ **Complexity**
80
+
81
+ - `O(n)`
82
+
83
+ ## Verified
84
+
85
+ - [H - Two SAT](https://atcoder.jp/contests/practice2/tasks/practice2_h)
86
+ - [163 ms](https://atcoder.jp/contests/practice2/submissions/16655036 )
87
+
88
+ ## Links
89
+
90
+ - AtCoder Library(ACL)
91
+ - [Documetn twosat.html](https://atcoder.github.io/ac-library/master/document_ja/twosat.html)
@@ -0,0 +1,3 @@
1
+ See [DSU document (dsu.md)](https://github.com/universato/ac-library-rb/blob/main/document_en/dsu.md).
2
+
3
+ DSU is an alias of UnionFind.
@@ -0,0 +1,64 @@
1
+ # Convolution
2
+
3
+ 畳み込みを行います。長さ`N`の`Integer`の配列`a[0],a[1],...,a[N-1]`と長さ`M`の`Integer`の配列`b[0],b[1],...,b[M-1]`から畳み込みを計算し、長さ`N+M-1`の`Integer`の配列`c`として返します。
4
+
5
+ ## convolution
6
+
7
+ ```ruby
8
+ (1) conv = Convolution.new(m = 998244353)
9
+ (2) conv = Convolution.new(m, primitive_root)
10
+ ```
11
+
12
+ 畳み込みを`mod m`で計算するためのオブジェクトを作成します。
13
+
14
+ `primitive_root`は法`m`に対する原始根である必要があります。与えられなかった場合は、内部で最小の原始根を計算します。
15
+
16
+ **制約**
17
+
18
+ - `2≦m`
19
+
20
+ - `m`は素数
21
+
22
+ - ((2)のみ) `primitive_root`は法`m`に対する原始根
23
+
24
+ **計算量**
25
+
26
+ 1. `O(sqrt m)`
27
+
28
+ 2. `O(log m)`
29
+
30
+ ### 使用方法
31
+
32
+ 実際の計算は、上で作成したオブジェクト`conv`を用いて次のように行います。
33
+
34
+ ```ruby
35
+ c = conv.convolution(a, b)
36
+ ```
37
+
38
+ `a`と`b`の少なくとも一方が空配列の場合は空配列を返します。
39
+
40
+ **制約**
41
+
42
+ - `2^c|(m-1)`かつ`|a|+|b|-1<=2^c`なる`c`が存在する
43
+
44
+ **計算量**
45
+
46
+ - `O((|a|+|b|) log (|a|+|b|))`
47
+
48
+ ## convolution_ll
49
+
50
+ `convolution`の`m`として十分大きな素数を用いることで対応できます。
51
+
52
+ `1e15`を超える`NTT-Friendly`な素数の1例として、`1125900443713537 = 2^29×2097153+1`があります。
53
+
54
+ # Verified
55
+
56
+ - [C - 高速フーリエ変換](https://atcoder.jp/contests/atc001/tasks/fft_c)
57
+ - `m = 1012924417`
58
+ [1272ms](https://atcoder.jp/contests/atc001/submissions/17193829)
59
+ - `m = 1125900443713537`
60
+ [2448 ms](https://atcoder.jp/contests/atc001/submissions/17193739)
61
+
62
+ # 参考
63
+
64
+ - [本家 ACL のドキュメント Convolution](https://atcoder.github.io/ac-library/master/document_ja/convolution.html)
@@ -0,0 +1,183 @@
1
+ # DSU - Disjoint Set Union
2
+
3
+ 別名: Union Find (むしろ、こちらが有名)
4
+
5
+ 無向グラフに対して、
6
+
7
+ - 辺の追加(2頂点の連結)
8
+ - 2頂点が連結かの判定(別の頂点を通して行き来できることを含みます)
9
+
10
+ をならし`O(α(n))`時間で高速に計算できます。
11
+
12
+
13
+ また、内部的に、各連結成分ごとに代表元(代表となる頂点)を1つ持っています。
14
+
15
+ 辺の追加により連結成分がマージされるとき、元の連結成分の代表元のどちらかが新たな代表元になります。
16
+
17
+ ## 使い方
18
+
19
+ ```rb
20
+ d = DSU.new(5)
21
+ p d.groups # => [[0], [1], [2], [3], [4]]
22
+ p d.same?(2, 3) # => false
23
+ p d.size(2) # => 1
24
+
25
+ d.merge(2, 3)
26
+ p d.groups # => [[0], [1], [2, 3], [4]]
27
+ p d.same?(2, 3) # => true
28
+ p d.size(2) # => 2
29
+ ```
30
+
31
+ ## 特異メソッド
32
+
33
+ ### new(n = 0) -> DSU
34
+
35
+ ```rb
36
+ d = DSU.new(n)
37
+ ```
38
+
39
+ `n` 頂点, `0` 辺の無向グラフを生成します。
40
+
41
+ 頂点の番号は `0` 始まりで数え、`n - 1` までになります。
42
+
43
+ **計算量**
44
+
45
+ - `O(n)`
46
+
47
+
48
+ **エイリアス**
49
+
50
+ - `DSU`
51
+ - `DisjointSetUnion`
52
+ - `UnionFind`
53
+ - `UnionFindTree`
54
+
55
+ ## インスタンスメソッド
56
+
57
+ ### merge(a, b) -> Integer
58
+
59
+ ```rb
60
+ d.merge(a, b)
61
+ ```
62
+
63
+ 頂点 `a` と頂点 `b`を連結させます。
64
+ `a`, `b` が既に連結だった場合はその代表元、非連結だった場合は連結させたあとの新たな代表元を返します。
65
+
66
+ 計算量 ならしO(α(n))
67
+
68
+ **エイリアス**
69
+
70
+ - `merge`
71
+ - `unite`
72
+
73
+ ### same?(a, b) -> bool
74
+
75
+ ```rb
76
+ d.same?(a, b)
77
+ ```
78
+
79
+ 頂点aと頂点bが連結であるとき `true` を返し、そうでないときは `false` を返します。
80
+
81
+ **計算量**
82
+
83
+ - ならし `O(α(n))`
84
+
85
+ **エイリアス**
86
+
87
+ - `same?`
88
+ - `same`
89
+
90
+ ### leader(a) -> Integer
91
+
92
+ ```rb
93
+ d.leader(a)
94
+ ```
95
+
96
+ 頂点 `a` の属する連結成分の代表(根)の頂点を返します。
97
+
98
+ **計算量**
99
+
100
+ - ならし `O(α(n))`
101
+
102
+ **エイリアス**
103
+
104
+ - `leader`
105
+ - `root`
106
+ - `find`
107
+
108
+ ### size(a) -> Integer
109
+
110
+ ```rb
111
+ d.size(3)
112
+ ```
113
+
114
+ 頂点 `a` の属する連結成分の頂点数(サイズ)を返します。
115
+
116
+ **計算量**
117
+
118
+ - ならし `O(α(n))`
119
+
120
+ ### groups -> [[Integer]]
121
+
122
+ ```rb
123
+ d.groups
124
+ ```
125
+
126
+ グラフを連結成分に分けて、その情報を返します。
127
+
128
+ 返り値は2次元配列で、内側・外側ともに配列内の順番は未定義です。
129
+
130
+ **計算量**
131
+
132
+ - `O(n)`
133
+
134
+ ## Verified
135
+
136
+ - [A \- Disjoint Set Union](https://atcoder.jp/contests/practice2/tasks/practice2_a)
137
+
138
+ ## 参考リンク
139
+
140
+ - 当ライブラリ
141
+ - [当ライブラリの実装コード dsu.rb](https://github.com/universato/ac-library-rb/blob/master/lib/dsu.rb)
142
+ - [当ライブラリのテストコード dsu_test.rb](https://github.com/universato/ac-library-rb/blob/master/test/dsu_test.rb)
143
+ - 本家ライブラリ
144
+ - [本家ACLのドキュメント dsu.md](https://github.com/atcoder/ac-library/blob/master/document_ja/dsu.md)
145
+ - [本家ACLのコード dsu.hpp](https://github.com/atcoder/ac-library/blob/master/atcoder/dsu.hpp)
146
+
147
+ ## その他
148
+
149
+ ### DSUよりUnionFindの名称の方が一般的では?
150
+
151
+ UnionFindの方が一般的だと思いますが、本家ライブラリに合わせています。なお、`UnionFind`をクラスのエイリアスとしています。
152
+
153
+ https://twitter.com/3SAT_IS_IN_P/status/1310122929284210689 (2020/9/27)
154
+
155
+ Google Scholar によると
156
+ - "union find": 8,550件
157
+ - "union find data structure": 1,970件
158
+ - "disjoint set union": 1,610 件
159
+ - "disjoint set data structure": 1,030 件
160
+
161
+ ### メソッドのエイリアスについて
162
+
163
+ 本家ライブラリでは`same`ですが、真偽値を返すメソッドなのでRubyらしく`same?`をエイリアスとして持ちます。`same`はdeprecated(非推奨)ですので、`same?`を使って下さい。
164
+
165
+ 本家は`merge`ですが、`unite`もエイリアスに持ちます。`unite`は`UnionFind`に合っているし、蟻本などでも一般的にもよく使われています。
166
+
167
+ 本家は`leader`ですが、`UnionFind`に合っていて一般的であろう`find`や`root`もエイリアスとして持ちます。
168
+
169
+ ### mergeの返り値について
170
+
171
+ 本家ライブラリの実装に合わせて、`merge`メソッドは新たにマージしたか否かにかかわらず、代表元を返しています。
172
+
173
+ ただ、新たに結合した場合には代表元を返して、そうでない場合は`nil`か`false`を返すような`merge?`(あるいは`merge!`)を入れようという案があります。Rubyに, true/false以外を返す` nonzero?`などもあるので、`merge?`という名称は良いと思います。
174
+
175
+ ### 実装の説明
176
+
177
+ 本家ライブラリに合わせて、内部のデータを`@parent_or_size`というインスタンス変数名で持っています。これは、根(代表元)となる要素の場合は、その連結成分の要素数(サイズ)に-1を乗じた値を返し、それ以外の要素の場合に、その要素の属する連結成分の代表(根)の番号を返します。
178
+
179
+ なお、インスタンスが初期化され、まだどの頂点どうしも連結されていないときは、全ての頂点が自分自身を代表元とし、サイズ1の連結成分が頂点の数だけできます。そのため、初期化されたときは、内部の配列`@parent_or_size`は、要素が全て-1となります。
180
+
181
+ ### 変更履歴
182
+
183
+ 2020/10/25 [PR #64] メソッド`groups`(正確には内部で定義されている`groups_with_leader`)のバグを修正しました。