public List <string> Split(string s, int maxWordLength, Func <double, double, double, double, double, double> method, bool verbose) { try { if (verbose) { Trace.Indent(); } if (verbose) { Trace.WriteLine("Getting FPL..."); } var fpl = FrequencyPerLength(); if (verbose) { Trace.Write("OK"); } int n = s.Length; List <string> ans = new List <string>(); int[] pre = new int[n + 1], cnt = new int[n + 1]; double[] dp = new double[n + 1]; dp[0] = 0; for (int i = 1; i <= n; i++) { dp[i] = double.NegativeInfinity; } pre[0] = 1;//crutial to make 0-pre[0]<0 when tracing back cnt[0] = 0; if (verbose) { Trace.WriteLine("DPing..."); } int percentage = -1; for (int i = 0; i < n; i++) { Parallel.For(1, Math.Min(n - i, maxWordLength) + 1, (l) => { double probLog = method(l, Count(s.Substring(i, l)), Entropy(s.Substring(i, l)), fpl[l].mean, fpl[l].stderr);//count,entropy var v = dp[i] + probLog; if (v > dp[i + l]) { dp[i + l] = v; cnt[i + l] = cnt[i] + 1; pre[i + l] = l; } }); if (i > 0 && (i + 1) * 100L / n > percentage) { if (verbose) { Trace.WriteLine($"DPing... {++percentage}% Ex: {s.Substring(i - pre[i], pre[i])} scored {dp[i]} avg {(double)i / cnt[i]} words"); } } } if (verbose) { Trace.WriteLine("Tracing back..."); } List <int> idxs = new List <int>(); for (int i = n; i >= 0; i -= pre[i]) { idxs.Add(i); } if (verbose) { Trace.WriteLine("Picking words..."); } percentage = -1; for (int i = idxs.Count - 1; i > 0; i--) { string _s = s.Substring(idxs[i], idxs[i - 1] - idxs[i]); WordIdentified?.Invoke(_s); ans.Add(_s); if ((idxs.Count - i + 1) * 100L / idxs.Count > percentage) { if (verbose) { Trace.WriteLine($"Picking words... {++percentage}% Ex: {_s}"); } } } if (verbose) { Trace.Write(" => OK"); } SplittedWords = ans; IsBuilt = true; return(ans); } finally { if (verbose) { Trace.Unindent(); } } }