@@ -46,29 +46,35 @@ public static AnalysisResults Analyze(
4646 /// <summary>Try to find the minimal unique substring index/length to use for comparisons.</summary>
4747 private static bool TryUseSubstring ( ReadOnlySpan < string > uniqueStrings , bool ignoreCase , int minLength , int maxLength , out AnalysisResults results )
4848 {
49- const int MaxSubstringLengthLimit = 8 ; // arbitrary small-ish limit... t's not worth the increase in algorithmic complexity to analyze longer substrings
49+ const int MaxSubstringLengthLimit = 8 ; // arbitrary small-ish limit... it's not worth the increase in algorithmic complexity to analyze longer substrings
50+ int uniqueStringsLength = uniqueStrings . Length ;
51+
52+ // Sufficient uniqueness factor of 95% is good enough.
53+ // Instead of ensuring that 95% of data is good, we stop when we know that at least 5% is bad.
54+ int acceptableNonUniqueCount = uniqueStringsLength / 20 ;
5055
5156 SubstringComparer comparer = ignoreCase ? new JustifiedCaseInsensitiveSubstringComparer ( ) : new JustifiedSubstringComparer ( ) ;
5257 HashSet < string > set = new HashSet < string > (
5358#if NET6_0_OR_GREATER
54- uniqueStrings . Length ,
59+ uniqueStringsLength ,
5560#endif
5661 comparer) ;
5762
58- // For each substring length...
63+ // For each substring length...preferring the shortest length that provides
64+ // enough uniqueness
5965 int maxSubstringLength = Math . Min ( minLength , MaxSubstringLengthLimit ) ;
6066 for ( int count = 1 ; count <= maxSubstringLength ; count ++ )
6167 {
6268 comparer . IsLeft = true ;
6369 comparer . Count = count ;
6470
65- // For each index, get a uniqueness factor for the left-justified substrings.
71+ // For each index from , get a uniqueness factor for the left-justified substrings.
6672 // If any is above our threshold, we're done.
6773 for ( int index = 0 ; index <= minLength - count ; index ++ )
6874 {
6975 comparer . Index = index ;
7076
71- if ( HasSufficientUniquenessFactor ( set , uniqueStrings ) )
77+ if ( HasSufficientUniquenessFactor ( set , uniqueStrings , acceptableNonUniqueCount ) )
7278 {
7379 results = CreateAnalysisResults (
7480 uniqueStrings , ignoreCase , minLength , maxLength , index , count ,
@@ -90,10 +96,9 @@ private static bool TryUseSubstring(ReadOnlySpan<string> uniqueStrings, bool ign
9096 // If any is above our threshold, we're done.
9197 for ( int index = 0 ; index <= minLength - count ; index ++ )
9298 {
93- // Get a uniqueness factor for the right-justified substrings.
94- // If it's above our threshold, we're done.
9599 comparer . Index = - index - count ;
96- if ( HasSufficientUniquenessFactor ( set , uniqueStrings ) )
100+
101+ if ( HasSufficientUniquenessFactor ( set , uniqueStrings , acceptableNonUniqueCount ) )
97102 {
98103 results = CreateAnalysisResults (
99104 uniqueStrings , ignoreCase , minLength , maxLength , comparer . Index , count ,
@@ -202,7 +207,7 @@ internal static unsafe bool IsAllAscii(ReadOnlySpan<char> s)
202207#if NET8_0_OR_GREATER
203208 private static readonly SearchValues < char > s_asciiLetters = SearchValues . Create ( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ) ;
204209#endif
205- private static bool ContainsAnyLetters ( ReadOnlySpan < char > s )
210+ internal static bool ContainsAnyLetters ( ReadOnlySpan < char > s )
206211 {
207212 Debug . Assert ( IsAllAscii ( s ) ) ;
208213
@@ -221,14 +226,10 @@ private static bool ContainsAnyLetters(ReadOnlySpan<char> s)
221226#endif
222227 }
223228
224- private static bool HasSufficientUniquenessFactor ( HashSet < string > set , ReadOnlySpan < string > uniqueStrings )
229+ internal static bool HasSufficientUniquenessFactor ( HashSet < string > set , ReadOnlySpan < string > uniqueStrings , int acceptableNonUniqueCount )
225230 {
226231 set . Clear ( ) ;
227232
228- // Sufficient uniqueness factor of 95% is good enough.
229- // Instead of ensuring that 95% of data is good, we stop when we know that at least 5% is bad.
230- int acceptableNonUniqueCount = uniqueStrings . Length / 20 ;
231-
232233 foreach ( string s in uniqueStrings )
233234 {
234235 if ( ! set . Add ( s ) && -- acceptableNonUniqueCount < 0 )
0 commit comments