Пример #1
0
        /// <summary>
        /// given 2 arrays, finds the longest sub array they have in common in o ( (a.Length * log(a.Length)  ) time using hash
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="toLong"></param>
        /// <returns>the longest sub array they have in common</returns>
        public static List <T> LongestCommonSubArrayWithHash(IList <T> a, IList <T> b, Func <T, long> toLong)
        {
            int maxPowerForNormalization = Math.Max(a.Count, b.Count);
            var hashA      = new ArrayHashComputer <T>(a, toLong, maxPowerForNormalization);
            var hashB      = new ArrayHashComputer <T>(b, toLong, maxPowerForNormalization);
            int minLength  = 0;
            int maxLength  = Math.Min(a.Count, b.Count);
            int firstIndex = -1;

            while (minLength < maxLength)
            {
                var length          = (minLength + maxLength + 1) / 2;
                int firstValidIndex = hashA.FirstIndexOfSameSubArrayWithLength(hashB, length);
                if (firstValidIndex != -1)
                {
                    firstIndex = firstValidIndex;
                    minLength  = length;
                }
                else
                {
                    maxLength = length - 1;
                }
            }
            //return minLength; //uncomment if we just want the length of the common sub string
            var result = new List <T>(minLength);

            for (int i = firstIndex; i < firstIndex + minLength; ++i)
            {
                result.Add(a[i]);
            }
            return(result);
        }
Пример #2
0
        /// <summary>
        /// Find longest palindrome in 'a' in o (a.Length * Log(a.Length)  time
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="a"></param>
        /// <param name="toLong"></param>
        /// <returns>
        /// Item1: length od the maximum palindrome
        /// Item2: index of the first palindrome with this length
        /// </returns>
        public static Tuple <int, int> LongestPalindrome(List <T> a, Func <T, long> toLong)
        {
            if (a.Count <= 1)
            {
                return(Tuple.Create(a.Count, 0));
            }
            var aReverse = new List <T>(a);

            aReverse.Reverse();
            var             hashA                   = new ArrayHashComputer <T>(a, toLong, a.Count);
            var             hashReverse             = new ArrayHashComputer <T>(aReverse, toLong, a.Count);
            Func <int, int> palindromeLengthToIndex = (l => IndexFirstPalindromeOfLength(l, hashA, hashReverse));
            int             maxEvenLengthPalindrome = 2 * Utils.MaximumValidIndex(0, a.Count / 2, halfLength => palindromeLengthToIndex(2 * halfLength) != -1);
            int             maxOddLengthPalindrome  = 2 * Utils.MaximumValidIndex(0, (a.Count - 1) / 2, halfLength => palindromeLengthToIndex(2 * halfLength + 1) != -1) + 1;
            int             maxPalindromeLength     = Math.Max(maxEvenLengthPalindrome, maxOddLengthPalindrome);
            var             maxIndex                = palindromeLengthToIndex(maxPalindromeLength);

            return(Tuple.Create(maxPalindromeLength, maxIndex));
        }
Пример #3
0
 private static int IndexFirstPalindromeOfLength(int l, ArrayHashComputer <T> a, ArrayHashComputer <T> aReversed)
 {
     Debug.Assert(a.Length == aReversed.Length);
     if (l <= 1)
     {
         return(0);
     }
     for (int start = 0; start < (a.Length - l + 1); ++start)
     {
         int end          = start + l / 2 - 1;
         var aHash        = a.Hash(start, end);
         int reverStart   = a.Length - (start + l);
         var aReverseHash = aReversed.Hash(reverStart, reverStart + l / 2 - 1);
         if (aHash == aReverseHash)
         {
             return(start);
         }
     }
     return(-1);
 }
Пример #4
0
        /// <summary>
        /// finds the index of first sub array of length 'subArrayLength' that can be found both in 'this and 'other' array in o (this.Length) time
        /// if 'subArrayLength == 0', it will return 0 (the first occurence of an empty string is at index 0)
        /// </summary>
        /// <param name="other"></param>
        /// <param name="subArrayLength">the exact length of the sub array to find</param>
        /// <returns>index of the sub array in the 'this' array, or -1 if no such array of length 'subArrayLength' exists</returns>
        public int FirstIndexOfSameSubArrayWithLength(ArrayHashComputer <T> other, int subArrayLength)
        {
            if (subArrayLength <= 0)
            {
                return(0);
            }
            var hashInOtherArray = new HashSet <long>();

            for (var startIndex = 0; startIndex <= other.Length - subArrayLength; ++startIndex)
            {
                hashInOtherArray.Add(other.Hash(startIndex, startIndex + subArrayLength - 1));
            }
            for (var startIndex = 0; startIndex <= Length - subArrayLength; ++startIndex)
            {
                if (hashInOtherArray.Contains(Hash(startIndex, startIndex + subArrayLength - 1)))
                {
                    return(startIndex);
                }
            }
            return(-1);  //there is no common array of length 'subArrayLength' in 'this' and 'other' array
        }
Пример #5
0
 /// <summary>
 /// given 2 strings, finds a smaller string that is the longest substring they have in common (using hash)
 /// Complexity:         o( a.Length * log(a.Length)) )
 /// </summary>
 /// <param name="a"></param>
 /// <param name="b"></param>
 /// <returns></returns>
 public static string LongestCommonSubstring_With_Hash(string a, string b)
 {
     return(new string(ArrayHashComputer <char> .LongestCommonSubArrayWithHash(a.ToList(), b.ToList(), x => x).ToArray()));
 }
Пример #6
0
 /// <summary>
 /// Find longest palindrome in 's' (using hash)
 /// Complexity:        o( a.Length * Log(a.Length) )
 /// Memory Complexity: o( a.Length )
 /// </summary>
 /// <returns>
 /// Item1: length od the maximum palindrome
 /// Item2: index of the first palindrome with this length
 /// </returns>
 public static Tuple <int, int> LongestPalindromeWithHash(string s)
 {
     return(ArrayHashComputer <char> .LongestPalindrome(s.ToList(), x => x));
 }