1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
//! 接尾辞配列。

use std::cmp::Ordering::{Equal, Greater, Less};
use std::collections::{BTreeMap, BTreeSet};
use std::fmt::Debug;
use std::ops::Index;

/// 接尾辞配列。
///
/// 文字列 $S$ の各接尾辞を辞書順でソートしたもの。
/// より正確には、$i$ ($0\\le i\\le |S|$) を $S\[i\\dots\]$ をキーとしてソートした配列 $A$ である。
///
/// # Idea
/// ## 用語の定義など
///
/// 文字列 $S$ について、 $S\[|S|\]$ には辞書順最小の文字が入っていると見なす。
/// また、$S\[|S|+1\]$ には辞書順最大の文字が入っていると見なしている気がする。
///
/// 以下、$S\[i\\dots\]$ を接尾辞 $i$ と呼ぶ。
/// また、例として文字列 `GTCCCGATGTCATGTCAGGA$` を考える。
///
/// ```text
///  G  T  C  C  C  G  A  T  G  T  C  A  T  G  T  C  A  G  G  A  $
///  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
/// ```
///
/// この文字列の接尾辞配列は次のようになる。
///
/// ```text
///  20 19 16 11  6 15 10  2  3  4 18  5 17 13  8  0 14  9  1 12  7
/// ```
///
/// ### S-type と L-type
///
/// まず、接尾辞に対して _S-type_ と _L-type_ を定義する。
/// 接尾辞 $i$ が接尾辞 $i+1$ より辞書順で小さい (smaller)
/// とき、接尾辞 $i$ を S-type であると言う。そうでない (larger) とき、L-type
/// であると言う。長さが異なるので、等しくなることはないことに注意せよ。
/// なお、接尾辞 $|S|$ は S-type とする。
/// また、簡単のため、単に「$i$ が S-type である」などと言う。
///
/// $i$ ($0\\le i \\lt |S|$) について次が成り立つので、$|S|$ が S-type
/// であることと合わせて、末尾から順に線形時間で求められる。
///
/// - $S\[i\] \\lt S\[i+1\]$ なら、$i$ は S-type。
/// - $S\[i\] \\gt S\[i+1\]$ なら、$i$ は L-type。
/// - $S\[i\] = S\[i+1\]$ なら、$i$ と $i+1$ は同じ type。
///
/// ### LMS suffix と LMS block
///
/// $i-1$ が L-type であるような S-type の $i$ を、特に
/// LMS (leftmost S-type) suffix と言う。$0$ は LMS ではないことに注意せよ。
/// また、LMS suffix を、次の LMS suffix(存在すれば)の開始位置で区切ったものを
/// LMS block と呼ぶ。LMS block は次のようになる。
///
/// ```text
///  G  T  C  C  C  G  A  T  G  T  C  A  T  G  T  C  A  G  G  A  $
///  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
///  S  L *S  S  S  L *S  L *S  L  L *S  L *S  L  L *S  L  L  L *S
///       [------------]
///                   [------]
///                         [---------]
///                                  [------]
///                                        [---------]
///                                                 [------------]
///                                                             []
/// ```
///
/// ### バケット
///
/// 接尾辞配列を再掲する。ただし、各 $i$ に対して、その type と $S\[i\]$ を併記する。
/// ただし、`*S` は LMS を表す。
///
/// ```text
///  20 19 16 11  6 15 10  2  3  4 18  5 17 13  8  0 14  9  1 12  7
///   $  A  A  A  A  C  C  C  C  C  G  G  G  G  G  G  T  T  T  T  T
///  *S  L *S *S *S  L  L *S  S  S  L  L  L *S *S  S  L  L  L  L  L
/// ```
///
/// 同じ文字で始まる接尾辞が連続していることに気づく。この一連の部分をバケットと呼ぶ。
/// たとえば、`19`, `16`, `11`, `6` の部分を指して `A` のバケットと呼ぶことにする。
///
/// さらに、各文字のバケットにおいて、L-type が前半に、S-type が後半に来ていることにも気づく。
/// これは、$S\[i\] = S\[j\] = c$ であるような接尾辞 $i$ (L-type) と $j$ (S-type)
/// を考えたとき、接尾辞 $i$ は $c$ が 1 つ以上続いた後に $c$ より小さい文字が現れ、
/// 接尾辞 $j$ は $c$ が 1 つ以上続いた後に $c$ より大きい文字が現れることから従う。
///
/// ### Induced sorting
///
/// この操作により、LMS block のソート順を得ることができる。この操作では、部分文字列
/// $S\[i\\dots j\]$ (inclusive) に辞書順最大の文字を連結したものを考え[^1]、この
/// $i$ をバケットに入れていく。$j$ については適宜説明する。ここでは、簡単のため
/// $S\[i\\dots j\]$ に辞書順最大の文字を連結したものを指して、単に部分文字列 $S\[i\\dots j\]$
/// と呼ぶことにする。
///
/// [^1]: よくある説明では suffix $S\[i\\dots\]$ だと思いますが、
/// それだと納得のいく説明ができなかったのでこういう説明になりました。
/// 「LMS suffix がソート順に並んでいるときに IS をすると SA
/// が得られます」というのが示されたあと、適当な順で LMS suffix を入力して
/// IS を実行されると、もやもやします。
///
/// まず、LMS suffix たちの添字 $i$ は得られているとし、それらを対応するバケットの
/// 末尾に適当な順に入れる。このとき $j = i$ とする。
///
/// ```text
///  20  -  6 11 16  -  -  -  -  2  -  -  -  -  8 13  -  -  -  -  -
///   $  A  A  A  A  C  C  C  C  C  G  G  G  G  G  G  T  T  T  T  T
///  *S  - *S *S *S  -  -  -  - *S  -  -  -  - *S *S  -  -  -  -  -
/// ```
///
/// ```text
/// 20 $X
///  - -
///  6 AX
/// 11 AX
/// 16 AX
///  - -
///  - -
///  - -
///  - -
///  2 CX
///  - -
///  - -
///  - -
///  - -
///  8 GX
/// 13 GX
///  - -
///  - -
///  - -
///  - -
///  - -
/// ```
///
/// バケットを前から走査し、部分文字列 $S\[i\\dots j\]$ を見つけたとき、$i-1$ が L-type
/// であれば、文字 $S\[i-1\]$ に対応するバケットの空きの先頭に $S\[i-1\\dots j\]$ を入れる。
///
/// まず、この操作によりバケットに追加された部分文字列がソート済みであることを帰納的に示す。
/// 初期状態では明らかにソート済みである。$S\[i\\dots j\]$ を見て $S\[i-1\\dots j\]$
/// を入れるとき、同一バケット内の L-type の各 $S\[i\'-1\\dots j\'\]$ に対して
/// $S\[i\'-1\\dots j\'\] \\lt S\[i-1\\dots j\]$ を示せば十分である(LMS については明らかなので)。
/// これは、$S\[i\'-1\] = S\[i-1\]$ のとき $S\[i\'-1\\dots j\'\] \\lt S\[i-1\\dots j\] \\iff
/// S\[i\'\\dots j\'\] \\lt S\[i\\dots j\]$ であることと、$i\'$ が $i$ より先に処理されているため
/// $S\[i\'\\dots j\'\] \\lt S\[i\\dots j\]$ であることから従う。
///
/// 次に、L-type であるすべての $i$ がバケットに入っていることを示す。
/// $i+1$ が LMS であれば、定義から $i$ は L-type であり、これはバケットに入れられる。
/// L-type である各 $i$ について $S\[i\\dots j\] \\gt S\[i+1\\dots j\]$ なので、
/// $i+1$ がバケットに入っているならば、$i$ もバケットに入れられる。
///
/// ```text
///  20 19  6 11 16 10 15  -  -  2 18  5 17  -  8 13  9 14  1  7 12
///   $  A  A  A  A  C  C  C  C  C  G  G  G  G  G  G  T  T  T  T  T
///  *S  L *S *S *S  L  L  -  - *S  L  L  L  - *S *S  L  L  L  L  L
/// ```
///
/// ```text
/// 20 $X
/// 19 A$X
///  6 AX
/// 11 AX
/// 16 AX
/// 10 CAX
/// 15 CAX
///  - -
///  - -
///  2 CX
/// 18 GA$X
///  5 GAX
/// 17 GGA$X
///  - -
///  8 GX
/// 13 GX
///  9 TCAX
/// 14 TCAX
///  1 TCX
///  7 TGX
/// 12 TGX
/// ```
///
/// 次に、バケットから LMS を取り除き、逆順から同様の操作を S-type について行う。
/// すなわち、バケットを後ろから走査し、部分文字列 $S\[i\\dots j\]$ を見つけたとき、
/// $i-1$ が S-type であれば、文字 $S\[i-1\]$ に対応するバケットの空きの末尾に
/// $S\[i-1\\dots j\]$ を入れる。
///
/// L-type のときと同様の議論から、すべての S-type の $i$ がソート順で得られることがわかる。
/// S-type と L-type の性質から、すべての $i$ についてソート順で得られたことになる。
///
/// ```text
///  20 19 16  6 11 10 15  2  3  4 18  5 17  8 13  0  9 14  1  7 12
///   $  A  A  A  A  C  C  C  C  C  G  G  G  G  G  G  T  T  T  T  T
///  *S  L *S *S *S  L  L *S  S  S  L  L  L *S *S  S  L  L  L  L  L
/// ```
///
/// ```text
/// 20 $X
/// 19 A$X
/// 16 AGGA$X
///  6 ATGX
/// 11 ATGX
/// 10 CAX
/// 15 CAX
///  2 CCCGAX
///  3 CCGAX
///  4 CGAX
/// 18 GA$X
///  5 GAX
/// 17 GGA$X
///  8 GTCAX
/// 13 GTCAX
///  0 GTCX
///  9 TCAX
/// 14 TCAX
///  1 TCX
///  7 TGX
/// 12 TGX
/// ```
///
/// 各 LMS $i$ に対応する部分文字列が LMS block と等しくなることは簡単に示せて、
/// 以上より LMS block のソート順が得られることがわかった。なお、初めに LMS
/// をバケットに入れるときにソート順に入れていれば、$j = |S|$
/// としても同様の議論ができ、接尾辞配列が得られる。
///
/// ## アルゴリズムの概要
///
/// まず、$S$ を末尾から走査し、type を求める。
///
/// ```text
///  G  T  C  C  C  G  A  T  G  T  C  A  T  G  T  C  A  G  G  A  $
///  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
///  S  L *S  S  S  L *S  L *S  L  L *S  L *S  L  L *S  L  L  L *S
/// ```
///
/// 次に、LMS を出現順にバケットの末尾に置いて induced sorting を行う。
///
/// ```text
///  20  -  6 11 16  -  -  -  -  2  -  -  -  -  8 13  -  -  -  -  -
///   $  A  A  A  A  C  C  C  C  C  G  G  G  G  G  G  T  T  T  T  T
///  *S  - *S *S *S  -  -  -  - *S  -  -  -  - *S *S  -  -  -  -  -
/// ```
///
/// ```text
///  20 19  6 11 16 10 15  -  -  2 18  5 17  -  8 13  9 14  1  7 12
///   $  A  A  A  A  C  C  C  C  C  G  G  G  G  G  G  T  T  T  T  T
///  *S  L *S *S *S  L  L  -  - *S  L  L  L  - *S *S  L  L  L  L  L
/// ```
///
/// ```text
///  20 19 16  6 11 10 15  2  3  4 18  5 17  8 13  0  9 14  1  7 12
///   $  A  A  A  A  C  C  C  C  C  G  G  G  G  G  G  T  T  T  T  T
///  *S  L *S *S *S  L  L *S  S  S  L  L  L *S *S  S  L  L  L  L  L
/// ```
///
/// これにより、LMS block の正しいソート順が得られる。
/// `*S` の添字を得られた順に並べると `20 16 6 11 2 8 13` となり、対応する
/// LMS block を順に並べると次のようになる[^2]。
///
/// [^2]: `$` で始まる `<pre>` がシェルスクリプトではない例。
///
/// ```text
/// $ AGGA$ ATG ATG CCCGA GTCA GTCA
/// ```
///
/// これはソート順で得られているので、隣同士の要素を比較するだけで、各要素の順序づけがわかる。
/// 等しい要素があることに注意せよ。
///
/// ```text
///  G  T  C  C  C  G  A  T  G  T  C  A  T  G  T  C  A  G  G  A  $
///  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
///  S  L *S  S  S  L *S  L *S  L  L *S  L *S  L  L *S  L  L  L *S
///       [----------][----][-------][----][-------][----------][]
///                  3     2        4     2        4           1 0
/// ```
///
/// この順序づけによってできる列 (_reduced string_) `3 2 4 2 4 1 0` の接尾辞配列は
/// 再帰的に SA-IS によって求めることができ、`6 5 3 1 0 4 2` となる。
///
/// LMS block たちをそのまま連結させると境界部分の文字が重複するのが気になる。
/// reduced string 中にも暗黙にそれらの重複があるが、それが許されることに触れておく。
/// 等しいペアについては、重複の 1 文字目で等しければ 2 文字目でも等しいので、
/// 辞書順比較には影響しない。等しくないペアについて、`$` 以外の LMS block の形は
/// `SS..SLL..LS` であり、最悪時でも片方に `LS` が現れた時点で大小関係が決まるので、
/// 重複部分まで走査されることがない。
///
/// これを元の文字列に対応させることで、LMS suffix のソート順が `20 16 11 6 2 13 8`
/// であるとわかり、これを用いて再度 induced sorting を行う。
///
/// ```text
///  20  - 16 11  6  -  -  -  -  2  -  -  -  - 13  8  -  -  -  -  -
///   $  A  A  A  A  C  C  C  C  C  G  G  G  G  G  G  T  T  T  T  T
///  *S  - *S *S *S  -  -  -  - *S  -  -  -  - *S *S  -  -  -  -  -
/// ```
///
/// ```text
///  20 19 16 11  6 15 10  -  -  2 18  5 17  - 13  8 14  9  1 12  7
///   $  A  A  A  A  C  C  C  C  C  G  G  G  G  G  G  T  T  T  T  T
///  *S  L *S *S *S  L  L  -  - *S  L  L  L  - *S *S  L  L  L  L  L
/// ```
///
/// ```text
///  20 19 16 11  6 15 10  2  3  4 18  5 17 13  8  0 14  9  1 12  7
///   $  A  A  A  A  C  C  C  C  C  G  G  G  G  G  G  T  T  T  T  T
///  *S  L *S *S *S  L  L *S  S  S  L  L  L *S *S  S  L  L  L  L  L
/// ```
///
/// これにより、所望の接尾辞配列が得られる。
///
/// 再帰の base case は、列の各要素が distinct な場合で、逆順列が接尾辞配列となる。
/// 連続して LMS suffix が現れないことと、先頭位置は LMS にならないことから、
/// reduced string は元の文字列の半分以下の長さになることがわかる。
/// よって、長さ $n$ での計算量を $T(n)$ とおくと、$T(1) \\in O(1)$ より次のようになる。
/// $$ T(n) \\le T(n/2) + O(n) \\in O(n). $$
///
/// ## パターン検索
///
/// パターン文字列 $T$ の $S$ における出現位置を検索する。
///
/// 範囲 $\[0\\dots |S|\]$ を接尾辞配列 $A$ 上で二分探索する。
/// これは、$S\[A\[i\]\\dots\]$ が $i$ に対して単調増加であることから可能。
/// 境界の両端を求めることで全列挙したり、片側のみを求めてパターンの有無のみを調べたりできる。
///
/// # Complexity
/// 入力中の文字の種類を $\\sigma$、文字列長を $n$ とする。
/// SA-IS を用いて構築するため、前処理は $O(\\sigma\\log(\\sigma)+n)$ 時間。
///
/// ↑ `todo!()` `String` なら $O(\\sigma+n)$、`[T]` なら mapping に時間がかかって $O(n\\log(\\sigma))$
/// っぽそう。値の範囲が `0..n` に収まるような `[usize]` に対しては $O(n)$ でできるから、追記かも。
///
/// 検索は、パターン長を $m$ として $O(m\\log(n))$ 時間。
///
/// # References
/// - Nong, Ge, Sen Zhang, and Wai Hong Chan. "Two efficient algorithms for linear time suffix array construction." _IEEE Transactions on Computers_ 60, no. 10 (2010): 1471--1484.
/// - Ko, Pang, and Srinivas Aluru. "Space efficient linear time construction of suffix arrays." In _Annual Symposium on Combinatorial Pattern Matching_, pp. 200--210. Springer, Berlin, Heidelberg, 2003.
///
/// ## See also
/// [CS166](http://web.stanford.edu/class/archive/cs/cs166/cs166.1206/lectures/04/Slides04.pdf)。
/// 差分スライドの関係でページ数がめちゃくちゃ多くて重いので注意。軽いのは
/// [こっち](http://web.stanford.edu/class/archive/cs/cs166/cs166.1206/lectures/04/Small04.pdf)。
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SuffixArray<T: Ord> {
    buf: Vec<T>,
    sa: Vec<usize>,
}

impl<T: Ord> From<Vec<T>> for SuffixArray<T> {
    fn from(buf: Vec<T>) -> Self {
        let buf_usize = hash(&buf);
        let sa = sa_is(&buf_usize);
        Self { buf, sa }
    }
}

impl From<String> for SuffixArray<char> {
    fn from(buf: String) -> Self {
        let buf: Vec<_> = buf.as_str().chars().collect();
        let buf_usize = hash_chars(&buf);
        let sa = sa_is(&buf_usize);
        Self { buf, sa }
    }
}

impl SuffixArray<u8> {
    pub fn from_bytes(buf: Vec<u8>) -> Self {
        let buf_usize = hash_bytes(&buf);
        let sa = sa_is(&buf_usize);
        Self { buf, sa }
    }
}

impl SuffixArray<usize> {
    pub fn from_hashed(buf: Vec<usize>) -> Self {
        assert!(Self::is_hashed(&buf));
        let buf_usize: Vec<_> =
            buf.iter().map(|&x| x + 1).chain(Some(0)).collect();

        let sa = sa_is(&buf_usize);
        Self { buf, sa }
    }

    fn is_hashed(buf: &[usize]) -> bool {
        let mut count = vec![0; buf.len()];
        for &x in buf {
            count[x] += 1;
        }
        (0..buf.len())
            .find(|&i| count[i] == 0)
            .map(|i| (i..count.len()).all(|i| count[i] == 0))
            .unwrap_or(true)
    }
}

/// 座標圧縮をする。
///
/// `buf` の末尾に辞書順最小の文字 `$` を付加した列を、座標圧縮して返す。
fn hash<T: Ord>(buf: &[T]) -> Vec<usize> {
    let enc: BTreeSet<_> = buf.iter().collect();
    let enc: BTreeMap<_, _> =
        enc.into_iter().enumerate().map(|(i, x)| (x, i)).collect();
    buf.iter()
        .map(|x| enc[x] + 1)
        .chain(std::iter::once(0)) // for '$'
        .collect()
}

/// 座標圧縮をする。
///
/// `buf` の末尾に辞書順最小の文字 `$` を付加した列を、座標圧縮して返す。`char`
/// の列を受け取り、バケットソートの要領で行う。
fn hash_chars(buf: &[char]) -> Vec<usize> {
    let max = match buf.iter().max() {
        Some(&c) => c as usize,
        None => return vec![0], // "$"
    };
    let enc = {
        let mut enc = vec![0; max + 1];
        for &c in buf {
            enc[c as usize] = 1;
        }
        for i in 1..=max {
            enc[i] += enc[i - 1];
        }
        enc
    };
    buf.iter().map(|&x| enc[x as usize])
        .chain(std::iter::once(0)) // for '$'
        .collect()
}

/// 座標圧縮をする。
///
/// `buf` の末尾に辞書順最小の文字 `$` を付加した列を、座標圧縮して返す。`u8`
/// の列を受け取り、バケットソートの要領で行う。
fn hash_bytes(buf: &[u8]) -> Vec<usize> {
    let enc = {
        let mut enc = vec![0; 256];
        for &b in buf {
            enc[b as usize] = 1;
        }
        for i in 1..=255 {
            enc[i] += enc[i - 1];
        }
        enc
    };
    buf.iter().map(|&x| enc[x as usize] )
        .chain(std::iter::once(0)) // for '$'
        .collect()
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum LsType {
    LType,
    SType(bool), // true iff leftmost S-type
}
use LsType::{LType, SType};

/// 出現回数を求める。
///
/// `res[x]` が `buf` における `x` の出現回数となる配列 `res` を返す。
///
/// # Requirements
/// `buf` の要素は `0..buf.len()` に含まれる。
fn count_freq(buf: &[usize]) -> Vec<usize> {
    let mut res = vec![0; buf.len()];
    buf.iter().for_each(|&x| res[x] += 1);
    res
}

/// 逆順列を返す。
///
/// `res[x]` が `buf` における `x` の出現位置となる配列 `res` を返す。
///
/// # Requirements
/// `buf` の要素は `0..buf.len()` に含まれ、かつ distinct である。
fn inv_perm(buf: &[usize]) -> Vec<usize> {
    let mut res = vec![0; buf.len()];
    buf.iter().enumerate().for_each(|(i, &x)| res[x] = i);
    res
}

/// LS type を求める。
///
/// `res[i]` が `buf[i]` の LS type である配列 `res` を返す。
fn ls_classify(buf: &[usize]) -> Vec<LsType> {
    let mut res = vec![SType(false); buf.len()];
    for i in (0..buf.len() - 1).rev() {
        res[i] = match buf[i].cmp(&buf[i + 1]) {
            Less => SType(false),
            Equal => res[i + 1],
            Greater => LType,
        };
    }
    for i in 1..buf.len() {
        if let (LType, SType(_)) = (res[i - 1], res[i]) {
            res[i] = SType(true);
        }
    }
    res
}

/// 各バケットの開始位置を求める。
///
/// # Input
/// `count[i]` が `i` 番目のバケットのサイズである配列 `count`。
fn bucket_head(count: &[usize]) -> Vec<usize> {
    let n = count.len();
    let mut head: Vec<_> =
        std::iter::once(&0).chain(&count[..n - 1]).cloned().collect();
    for i in 1..n {
        head[i] += head[i - 1];
    }
    head
}

/// 各バケットの終端位置を求める。
///
/// # Input
/// `count[i]` が `i` 番目のバケットのサイズである配列 `count`。
fn bucket_tail(count: &[usize]) -> Vec<usize> {
    let mut tail = count.to_vec();
    for i in 1..count.len() {
        tail[i] += tail[i - 1];
    }
    tail
}

/// すでに判明している SA と LS type から、SA の残りの要素を求める。
fn induce(
    buf: &[usize],
    sa: &mut [Option<usize>],
    count: &[usize],
    ls: &[LsType],
) {
    let mut head = bucket_head(count);
    for i in 0..sa.len() {
        if let Some(j) = sa[i] {
            if j > 0 && ls[j - 1] == LType {
                sa[head[buf[j - 1]]] = Some(j - 1);
                head[buf[j - 1]] += 1;
            }
        }
    }
    let mut tail = bucket_tail(count);
    for i in (1..count.len()).rev() {
        if let Some(j) = sa[i] {
            if j > 0 && ls[j - 1] != LType {
                tail[buf[j - 1]] -= 1;
                sa[tail[buf[j - 1]]] = Some(j - 1);
            }
        }
    }
}

/// 各 LMS block を文字とする文字列を作る。
///
/// 新たな文字も辞書順に番号づけられる。
///
/// # Examples
/// `[CCCG][AT][GTC][AT][GTC][AGGA][$]` → `3242410`
fn reduce(buf: &[usize], lms: &[usize], ls: &[LsType]) -> Vec<usize> {
    if lms.len() <= 1 {
        return vec![0; lms.len()];
    }

    let e = |(i0, i1)| {
        if (ls[i0], ls[i1]) == (SType(true), SType(true)) {
            Some(true)
        } else if ls[i0] != ls[i1] || buf[i0] != buf[i1] {
            Some(false)
        } else {
            None
        }
    };

    let mut map = vec![0; buf.len()]; // map[lms[0]] = 0
    map[lms[1]] = 1;
    let mut x = 1;
    for i in 2..lms.len() {
        let equiv = buf[lms[i]] == buf[lms[i - 1]]
            && (lms[i] + 1..).zip(lms[i - 1] + 1..).find_map(e).unwrap();
        if !equiv {
            x += 1;
        }
        map[lms[i]] = x;
    }

    (0..buf.len())
        .filter_map(|i| match ls[i] {
            SType(true) => Some(map[i]),
            _ => None,
        })
        .collect()
}

/// SA-IS により接尾辞配列を求める。
fn sa_is(buf: &[usize]) -> Vec<usize> {
    let len = buf.len();
    let count = count_freq(buf);
    if count.iter().all(|&x| x == 1) {
        return inv_perm(buf);
    }

    let ls = ls_classify(buf);
    let mut sa = vec![None; len];
    let mut tail = bucket_tail(&count);
    for i in (1..len).rev().filter(|&i| ls[i] == SType(true)) {
        tail[buf[i]] -= 1;
        sa[tail[buf[i]]] = Some(i);
    }

    induce(buf, &mut sa, &count, &ls);

    let lms: Vec<_> = sa
        .into_iter()
        .map(std::option::Option::unwrap)
        .filter(|&i| ls[i] == SType(true))
        .collect(); // in lexicographic order
    let rs_sa = sa_is(&reduce(buf, &lms, &ls));

    // in appearing order
    let lms: Vec<_> = (0..len).filter(|&i| ls[i] == SType(true)).collect();

    let mut tail = bucket_tail(&count);
    let mut sa = vec![None; len];
    for i in rs_sa.into_iter().rev() {
        let j = lms[i];
        tail[buf[j]] -= 1;
        sa[tail[buf[j]]] = Some(j);
    }
    induce(buf, &mut sa, &count, &ls);

    sa.into_iter().map(std::option::Option::unwrap).collect()
}

impl<T: Ord> SuffixArray<T> {
    /// パターン検索を行う。
    ///
    /// # Complexity
    ///
    /// $O(|T|\\log(|S|))$ 時間。
    ///
    /// # Examples
    ///
    /// ```
    /// use nekolib::seq::SuffixArray;
    ///
    /// let s: Vec<_> = "abracadabra".chars().collect();
    /// let sa: SuffixArray<_> = s.into();
    ///
    /// assert_eq!(sa.search(&['a']).collect::<Vec<_>>(), vec![10, 7, 0, 3, 5]);
    /// assert_eq!(
    ///     sa.search(&"abra".chars().collect::<Vec<_>>()).nth(1),
    ///     Some(0)
    /// );
    /// assert_eq!(sa.search(&['a', 'e']).next(), None);
    /// ```
    pub fn search(&self, pat: &[T]) -> impl Iterator<Item = usize> + '_ {
        let lo = {
            let mut lt = 1_usize.wrapping_neg();
            let mut ge = self.sa.len();
            while ge.wrapping_sub(lt) > 1 {
                let mid = lt.wrapping_add(ge.wrapping_sub(lt) / 2);
                let pos = self.sa[mid];
                match self.buf[pos..].cmp(pat) {
                    Less => lt = mid,
                    _ => ge = mid,
                }
            }
            ge
        };
        if lo >= self.sa.len() {
            return self.sa[lo..lo].iter().cloned();
        }
        let hi = {
            let mut le = lo.wrapping_sub(1);
            let mut gt = self.sa.len();
            while gt.wrapping_sub(le) > 1 {
                let mid = le.wrapping_add(gt.wrapping_sub(le) / 2);
                let pos = self.sa[mid];
                let len = pat.len().min(self.buf[pos..].len());
                match self.buf[pos..pos + len].cmp(pat) {
                    Greater => gt = mid,
                    _ => le = mid,
                }
            }
            gt
        };
        self.sa[lo..hi].iter().cloned()
    }

    /// 高さ配列を返す。
    ///
    /// # Examples
    /// ```
    /// use nekolib::seq::SuffixArray;
    ///
    /// let s: Vec<_> = "abracadabra".chars().collect();
    /// let sa: SuffixArray<_> = s.into();
    /// assert_eq!(sa.lcpa(), [0, 0, 1, 4, 1, 1, 0, 3, 0, 0, 0, 2]);
    /// ```
    pub fn lcpa(&self) -> Vec<usize> {
        let n = self.buf.len();
        let mut rank = vec![0; n + 1];
        for i in 0..=n {
            rank[self.sa[i]] = i;
        }
        let mut h = 0;
        let mut res = vec![0; n + 1];
        for i in 0..n {
            let j = self.sa[rank[i] - 1];
            if h > 0 {
                h -= 1;
            }
            while j + h < n && i + h < n {
                if self.buf[j + h] != self.buf[i + h] {
                    break;
                }
                h += 1;
            }
            res[rank[i]] = h;
        }
        res
    }

    /// 自身を消費し、内部表現を返す。
    ///
    /// # Examples
    ///
    /// ```
    /// use nekolib::seq::SuffixArray;
    ///
    /// let s: Vec<_> = "abracadabra".chars().collect();
    /// let sa: SuffixArray<_> = s.into();
    /// let sa = sa.into_inner();
    /// assert_eq!(sa, vec![11, 10, 7, 0, 3, 5, 8, 1, 4, 6, 9, 2]);
    /// ```
    pub fn into_inner(self) -> Vec<usize> { self.sa }
}

impl SuffixArray<char> {
    /// パターン文字列検索を行う。
    ///
    /// # Examples
    /// ```
    /// use nekolib::seq::SuffixArray;
    ///
    /// let sa: SuffixArray<_> = "abracadabra".to_string().into();
    /// let occ: Vec<_> = sa.search_str("ab").collect();
    /// assert_eq!(occ, vec![7, 0]);
    /// let occ: Vec<_> = sa.search_str("a").collect();
    /// assert_eq!(occ, vec![10, 7, 0, 3, 5]);
    /// assert_eq!(sa.search_str("e").next(), None);
    /// ```
    pub fn search_str(&self, pat: &str) -> impl Iterator<Item = usize> + '_ {
        let pat: Vec<_> = pat.chars().collect();
        self.search(&pat)
    }
}

impl<T: Ord> Index<usize> for SuffixArray<T> {
    type Output = usize;
    fn index(&self, i: usize) -> &usize { &self.sa[i] }
}

impl<T: Ord> From<SuffixArray<T>> for Vec<usize> {
    fn from(sa: SuffixArray<T>) -> Self { sa.sa }
}

#[test]
fn test_simple() {
    let buf = "abracadabra".to_string();
    let sa: SuffixArray<_> = buf.into();
    let sa: Vec<_> = sa.into();
    assert_eq!(sa, [11, 10, 7, 0, 3, 5, 8, 1, 4, 6, 9, 2])
}

#[test]
fn test_empty_text() {
    let sa: SuffixArray<_> = "".to_string().into();
    let occ: Vec<_> = sa.search_str("").collect();
    assert_eq!(occ, [0]);
    assert_eq!(sa.search_str("x").next(), None);
}

#[test]
fn test_empty_pat() {
    let sa: SuffixArray<_> = "empty".to_string().into();
    let occ: Vec<_> = sa.search_str("").collect();
    assert_eq!(occ, [5, 0, 1, 2, 3, 4]);
}

#[test]
fn test_naive() {
    let n = 1000;
    let f = |x: &i32| Some((x * 29 + 71) % 143);
    let buf: Vec<_> = std::iter::successors(Some(2_i32), f).take(n).collect();
    let naive_sa = {
        let mut sa: Vec<_> = (0..=n).collect();
        sa.sort_unstable_by_key(|&i| &buf[i..]);
        sa
    };
    let sa: SuffixArray<_> = buf.into();
    let sa: Vec<_> = sa.into();
    assert_eq!(sa, naive_sa);
}