Skip to content

Instantly share code, notes, and snippets.

@jianminchen
Created April 11, 2016 23:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jianminchen/0f561b8afc1cdf23ab95a8b603cd2a3e to your computer and use it in GitHub Desktop.
Save jianminchen/0f561b8afc1cdf23ab95a8b603cd2a3e to your computer and use it in GitHub Desktop.
String Calculate Function - HackerRank - suffixArray solution C# - still time out
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StringCalculateFunctionSuffixArray
{
class Program
{
static void Main(string[] args)
{
string s = Console.ReadLine();
Console.WriteLine(getMaximumValue(s).ToString());
}
public static int getMaximumValue(string s)
{
if (s == null || s.Length == 0) return 0;
int n = s.Length;
int pValue = 1;
HashSet<string> set = new HashSet<string>();
for (int i = 1; i <= n; i++) // substring length: i bug01: should be i<= n, not i< n
{
int start = 0;
int end = i - 1;
while (start <= n - 1 && end <= n - 1)
{
//string s1 = s.Substring(0, i); // bug 001 - i length of substring, but start position should vary
string s1 = s.Substring(start, i);
if (!set.Contains(s1)) // check if set has string
{
set.Add(s1);
int current = i * getCountSubstringUsingSuffixArray(s1, s);
if (current > pValue)
pValue = current;
}
start++;
end++;
}
}
return pValue;
}
/*
* using Boyer Algorithm
*/
private static int getCountSubstringUsingSuffixArray(string substring, string s)
{
var sa = SuffixArray.Build(s);
string pat = substring;
sa = sa.Search(pat);
return sa.Count();
}
}
/*
* source code from:
* https://blogs.msdn.microsoft.com/dhuba/2010/04/04/suffix-array/
*
* April 11, 2016
*
* Julia has to learn how to implement IEnumerable interface in a new class: SuffixArray
* here is the blog to read:
* https://msdn.microsoft.com/en-us/library/x7tax739(v=vs.110).aspx
*
* And then,
* public IEnumerator<int> GetEnumerator()
*
* IEnumerator IEnumerable.GetEnumerator()
*
* IEnumberable.GetEnumerator() has to be implmentated.
*/
// Suffix array represents simple text indexing mechanism.
public class SuffixArray : IEnumerable<int>
{
private const int c_lower = 0;
private const int c_upper = -1;
private readonly string m_text;
private readonly int[] m_pos;
private readonly int m_lower;
private readonly int m_upper;
SuffixArray(string text, int[] pos, int lower, int upper)
{
m_text = text;
m_pos = pos;
// Inclusive lower and upper boundaries define search range.
m_lower = lower;
m_upper = upper;
}
/*
* Julia goes over the function in detail:
* "aaaaaa"
*/
public static SuffixArray Build(string text)
{
// Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(text));
var length = text.Length;
// Sort starting positions of suffixes in lexicographical
// order.
var pos = Enumerable.Range(0, length).ToArray();
Array.Sort(pos, (x, y) => String.Compare(text, x, text, y, length));
// By default all suffixes are in search range.
return new SuffixArray(text, pos, 0, text.Length - 1);
}
public SuffixArray Search(string str)
{
//Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(str));
// Search range is empty so nothing to narrow.
if (m_lower > m_upper)
return this;
// Otherwise search for boundaries that enclose all
// suffixes that start with supplied string.
var lower = Search(str, c_lower);
var upper = Search(str, c_upper);
// Once precomputed sorted suffixes positions don't change
// but the boundaries do so that next refinement
// can be done within smaller range and thus faster.
// For example, you may narrow search range to suffixes
// that start with "ab" and then search within this smaller
// search range suffixes that start with "abc".
return new SuffixArray(m_text, m_pos, lower + 1, upper);
}
public IEnumerator<int> GetEnumerator()
{
// Enumerates starting positions of suffixes that fall
// into search range.
for (var i = m_lower; i <= m_upper; i++)
yield return m_pos[i];
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/*
* Julia:
* read String.Compare example, understand this api:
* https://msdn.microsoft.com/en-us/library/x7tax739(v=vs.110).aspx
*/
private int Compare(string w, int i)
{
// Comparison takes into account maximum length(w)
// characters. For example, strings "ab" and "abc"
// are thus considered equal.
return String.Compare(w, 0, m_text, m_pos[i], w.Length);
}
private int Search(string w, int bound)
{
// Depending on bound value binary search results
// in either lower or upper boundary.
int x = m_lower - 1, y = m_upper + 1;
if (Compare(w, m_lower) < 0)
return x;
if (Compare(w, m_upper) > 0)
return y;
while (y - x > 1)
{
var m = (x + y) / 2;
// If bound equals to 0 left boundary andvances to median
// only // if subject is strictly greater than median and
// thus search results in lower bound (position that
// preceeds first suffix equal to or greater than
// subject w). Otherwise search results in upper bound
// (position that preceeds fisrt suffix that is greater
// than subject).
if (Compare(w, m) > bound)
x = m;
else
y = m;
}
return x;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment