diff --git a/Source/ac-library-csharp/String/StringLib.cs b/Source/ac-library-csharp/String/StringLib.cs index 853af7f..20df0c6 100644 --- a/Source/ac-library-csharp/String/StringLib.cs +++ b/Source/ac-library-csharp/String/StringLib.cs @@ -389,6 +389,7 @@ public static int[] SaIs(ReadOnlySpan s, int upper, int thresholdNaive, int Induce(lms, s, sa, ls, sumS, sumL); // LMSを再帰的にソート + // m の値は再帰ごとに半分以下になるので再帰の回数も log(n) に抑えられる if (m > 0) { var sortedLms = new SimpleList(m); diff --git a/Test/ac-library-csharp.Test/String/StringLibTest.cs b/Test/ac-library-csharp.Test/String/StringLibTest.cs index bf30736..1692172 100644 --- a/Test/ac-library-csharp.Test/String/StringLibTest.cs +++ b/Test/ac-library-csharp.Test/String/StringLibTest.cs @@ -271,7 +271,7 @@ public void SAAllABTest() } } [Fact] - public void SA() + public void SuffixArray() { var s = "missisippi"; @@ -296,6 +296,26 @@ public void SA() s[sa[i]..].Should().Be(answer[i]); } } + [Fact] + public void SuffixArrayInt() + { + int[] s, sa; + s = Enumerable.Range(0, 500000).SelectMany(i => new[] { i, ~i }).ToArray(); + sa = StringLib.SuffixArray(s); + sa.Should().Equal( + Enumerable.Range(0, 500000).Select(i => 999999 - 2 * i).Concat( + Enumerable.Range(0, 500000).Select(i => 2 * i)) + ); + + s = Enumerable.Range(0, 1000000).ToArray(); + sa = StringLib.SuffixArray(s); + sa.Should().Equal(s); + + s = Enumerable.Range(0, 1000000).Reverse().ToArray(); + sa = StringLib.SuffixArray(s); + sa.Should().Equal(s); + } + [Fact] public void SASingle() {