Find byte sequence within a byte array - c#

I have a byte array and wish to find the "occurrences" of some bytes.
For example 00 69 73 6F 6D in a very large byte array (> 50/100 Megabytes)
OR
even better a reverse operation: Searching the most common pattern without knowing it the code should be able to read and find it from the file.

You can use the Boyer-Moore algorithm to efficiently search for a sequence of bytes in an array of bytes.
Here's a C# version I converted from the Java version from the Wikipedia entry on Boyer-Moore.
public sealed class BoyerMoore
{
readonly byte[] needle;
readonly int[] charTable;
readonly int[] offsetTable;
public BoyerMoore(byte[] needle)
{
this.needle = needle;
this.charTable = makeByteTable(needle);
this.offsetTable = makeOffsetTable(needle);
}
public IEnumerable<int> Search(byte[] haystack)
{
if (needle.Length == 0)
yield break;
for (int i = needle.Length - 1; i < haystack.Length;)
{
int j;
for (j = needle.Length - 1; needle[j] == haystack[i]; --i, --j)
{
if (j != 0)
continue;
yield return i;
i += needle.Length - 1;
break;
}
i += Math.Max(offsetTable[needle.Length - 1 - j], charTable[haystack[i]]);
}
}
static int[] makeByteTable(byte[] needle)
{
const int ALPHABET_SIZE = 256;
int[] table = new int[ALPHABET_SIZE];
for (int i = 0; i < table.Length; ++i)
table[i] = needle.Length;
for (int i = 0; i < needle.Length - 1; ++i)
table[needle[i]] = needle.Length - 1 - i;
return table;
}
static int[] makeOffsetTable(byte[] needle)
{
int[] table = new int[needle.Length];
int lastPrefixPosition = needle.Length;
for (int i = needle.Length - 1; i >= 0; --i)
{
if (isPrefix(needle, i + 1))
lastPrefixPosition = i + 1;
table[needle.Length - 1 - i] = lastPrefixPosition - i + needle.Length - 1;
}
for (int i = 0; i < needle.Length - 1; ++i)
{
int slen = suffixLength(needle, i);
table[slen] = needle.Length - 1 - i + slen;
}
return table;
}
static bool isPrefix(byte[] needle, int p)
{
for (int i = p, j = 0; i < needle.Length; ++i, ++j)
if (needle[i] != needle[j])
return false;
return true;
}
static int suffixLength(byte[] needle, int p)
{
int len = 0;
for (int i = p, j = needle.Length - 1; i >= 0 && needle[i] == needle[j]; --i, --j)
++len;
return len;
}
}
Here's some console app test code for it:
public static void Main()
{
byte[] haystack = new byte[10000];
byte[] needle = { 0x00, 0x69, 0x73, 0x6F, 0x6D };
// Put a few copies of the needle into the haystack.
for (int i = 1000; i <= 9000; i += 1000)
Array.Copy(needle, 0, haystack, i, needle.Length);
var searcher = new BoyerMoore(needle);
foreach (int index in searcher.Search(haystack))
Console.WriteLine(index);
}
Note how the Search() method returns the indices of all the locations of the start of needle inside haystack.
If you just wanted the count, you could just do:
int count = new BoyerMoore(needle).Search(haystack).Count();
For your second question: I assume you are asking about finding the longest repeated sequence of bytes?
That's a much more complicated - and very different - question. If you want an answer for that, you should ask a separate question for it, but you should read the Wikipedia entry on the "longest repeated substring problem".

Related

Appending '0' using concat does not seem to work

I have a program that compares two integer value's length with this extension method
public static int NumDigits(this int n)
{
if (n < 0)
{
n = (n == int.MinValue) ? int.MaxValue : -n;
}
if (n < 10) return 1;
if (n < 100) return 2;
if (n < 1000) return 3;
if (n < 10000) return 4;
if (n < 100000) return 5;
if (n < 1000000) return 6;
if (n < 10000000) return 7;
if (n < 100000000) return 8;
return n < 1000000000 ? 9 : 10;
}
And it works perfectly. When I print the value of num1.numDigits(), the value returns 4 (it is worth '1111'. And my other integer: num2.numDigits() returns 2 (it is 11). This is great but when I actually compare them:
int[] rawNum2 = Arrays.DigitArr(num2);
if (num1.NumDigits() > num2.NumDigits())
{
int diff = num1.NumDigits() - num2.NumDigits();
for (int i = 1; i < diff; i++)
{
rawNum2.Append(0);
}
reversedNum2 = rawNum2.Reverse();
}
reversedNum2 is still '11' when it should be '0011'.
This is the class I compiled and used.
public static int[] Append(this int[] source, int value)
{
int[] newValue = source;
newValue = newValue.Concat(new[] { value }).ToArray();
return newValue;
}
public static int[] Reverse(this int[] array)
{
int[] arr = array;
for (int i = 0; i < arr.Length / 2; i++)
{
int tmp = arr[i];
arr[i] = arr[arr.Length - i - 1];
arr[arr.Length - i - 1] = tmp;
}
return arr;
}
public static int[] DigitArr(int n)
{
if (n == 0) return new int[1] { 0 };
var digits = new List<int>();
for (; n != 0; n /= 10)
digits.Add(n % 10);
var arr = digits.ToArray();
Array.Reverse(arr);
return arr;
}
Why is this happening?
You are discarding the return value of the Append method.
Change
rawNum2.Append(0);
to
rawNum2 = rawNum2.Append(0);
inside the for loop.
Your loop could be and should be simplified to:
rawNum2 = rawNum2.PadRight(num1.NumDigits(), '0')
To get the reversedNum2 as 0011 change your loop as below.
for (int i = 1; i <= diff; i++)
{
rawNum2=rawNum2.Append(0);
}
I made two changes changed the for loop to use i<=diff instead of i < diff
and assigning the return value from Append() method into the rawNum2.

Digit difference sort

So I am trying to solve this task "Digit Difference Sort" on Codefights
Given an array of integers, sort its elements by the difference of their largest and smallest digits.
In the case of a tie, that with the larger index in the array should come first.
Example
For a = [152, 23, 7, 887, 243], the output should be digitDifferenceSort(a) = [7, 887, 23, 243, 152].
Here are the differences of all the numbers:
152: difference = 5 - 1 = 4;
23: difference = 3 - 2 = 1;
7: difference = 7 - 7 = 0;
887: difference = 8 - 7 = 1;
243: difference = 4 - 2 = 2.
23 and 887 have the same difference, but 887 goes after 23 in a, so in the sorted array it comes first.
I have an issue with two numbers having the same difference. Here's what I wrote so far:
int[] digitDifferenceSort(int[] a) {
return a.OrderBy(x => difference(x)).ToArray();
}
int difference(int x)
{
int min = 9, max = 0;
do
{
int tmp = x % 10;
min = Math.Min(min, tmp);
max = Math.Max(max, tmp);
} while ((x /= 10) > 0);
return max - min;
}
Didn't do much (for example the output is still [7, 23, 887, 243, 152] rather than [7, 887, 23, 243, 152])
How do I make element with larger index come first in result? What should I use instead of OrderBy?
I don't consider your difference method, i assume it works fine.
To your question: you have to keep revered order of the array (that the items with the same difference arrive will be sorted reverse). To do it, you could just reverse you input array: all items with not identical difference will be ordered correctly, and with the same differece will be ordered reversed:
int[] digitDifferenceSort(int[] a)
{
return a.Reverse().OrderBy(x => difference(x)).ToArray();
}
Following is my code for the above question digit difference sort. I am also getting output when running in Eclipse but when I paste the code on code signal it gives me a null pointer exception.
package NormalPrograms;
import java.util.ArrayList;
import java.util.Collections;
public class DigitDifferenceSort {
// For index wise sorting in descending order
public static int[] sortingnumberindexwise(int[] a, ArrayList<Integer> index) {
int k = 0;
int[] res = new int[index.size()];
int[] finalres = new int[index.size()];
for (int i = a.length - 1; i >= 0; i--) {
for (int j = 0; j < index.size(); j++) {
if (a[i] == (int) index.get(j)) {
res[k] = i;
index.remove(j);
k++;
break;
}
}
}
int g = 0;
k = 0;
for (int i = 0; i < res.length; i++) {
finalres[g] = a[res[k]];
g++;
k++;
}
return finalres;
}
public static int[] finddigitDifferenceandSort(int[] p) {
int[] finres = new int[p.length];
for (int i = 0; i < finres.length; i++) {
finres[i] = p[i];
}
// This finres array act as an temp array and reused to make final result array
int digit = 0;
ArrayList<Integer> A = new ArrayList<Integer>();
ArrayList<ArrayList<Integer>> B = new ArrayList<ArrayList<Integer>>();
for (int i = 0; i < 10; i++) {
B.add(new ArrayList<Integer>());
}
for (int i = 0; i < p.length; i++) {
int temp = 0;
temp = p[i];
while (p[i] > 0) {
digit = p[i] % 10;
p[i] /= 10;
A.add(digit);
}
int b = Collections.max(A);
int c = Collections.min(A);
int diff = b - c;
B.get(diff).add(temp);
A.clear();
}
for (int i = 0; i < B.size(); i++) {
if (B.get(i).size() > 1) {
ArrayList<Integer> C = new ArrayList<Integer>();
for (int k = 0; k < B.get(i).size(); k++) {
C.add(B.get(i).get(k));
}
B.get(i).clear();
for (int j : sortingnumberindexwise(finres, C)) {
B.get(i).add(j);
}
} else {
continue;
}
}
int k = 0;
for (int i = 0; i < B.size(); i++) {
for (int j = 0; j < B.get(i).size(); j++) {
if (B.get(i).size() == 0)
continue;
else {
finres[k] = B.get(i).get(j);
k++;
}
}
}
return finres;
}
public static void main(String[] args) {
int[] a = { 12, 21, 1, 1, 1, 2, 2, 3 };
for (int i : finddigitDifferenceandSort(a)) {
System.out.print(i + " ");
}
}
}

Get longest substring between two strings

I have two words,
britanicaeng and
britanicahin
I need to find out the longest common word between these i.e, britanica.
How can I do this in C# ?
Try this method:
public static string FindLongestCommonSubstring(string s1, string s2)
{
int[,] a = new int[s1.Length + 1, s2.Length + 1];
int row = 0; // s1 index
int col = 0; // s2 index
for (var i = 0; i < s1.Length; i++)
for (var j = 0; j < s2.Length; j++)
if (s1[i] == s2[j])
{
int len = a[i + 1, j + 1] = a[i, j] + 1;
if (len > a[row, col])
{
row = i + 1;
col = j + 1;
}
}
return s1.Substring(row - a[row, col], a[row, col]);
}
Usage example:
Console.WriteLine(FindLongestCommonSubstring("britanicaeng", "britanicahin"));
I refactored the C++ code from Ashutosh Singh at https://iq.opengenus.org/longest-common-substring-using-rolling-hash/ to create a rolling hash approach in C# - this will find the substring in O(N * log(N)^2) time and O(N) space
using System;
using System.Collections.Generic;
public class RollingHash
{
private class RollingHashPowers
{
// _mod = prime modulus of polynomial hashing
// any prime number over a billion should suffice
internal const int _mod = (int)1e9 + 123;
// _hashBase = base (point of hashing)
// this should be a prime number larger than the number of characters used
// in my use case I am only interested in ASCII (256) characters
// for strings in languages using non-latin characters, this should be much larger
internal const long _hashBase = 257;
// _pow1 = powers of base modulo mod
internal readonly List<int> _pow1 = new List<int> { 1 };
// _pow2 = powers of base modulo 2^64
internal readonly List<long> _pow2 = new List<long> { 1L };
internal void EnsureLength(int length)
{
if (_pow1.Capacity < length)
{
_pow1.Capacity = _pow2.Capacity = length;
}
for (int currentIndx = _pow1.Count - 1; currentIndx < length; ++currentIndx)
{
_pow1.Add((int)(_pow1[currentIndx] * _hashBase % _mod));
_pow2.Add(_pow2[currentIndx] * _hashBase);
}
}
}
private class RollingHashedString
{
readonly RollingHashPowers _pows;
readonly int[] _pref1; // Hash on prefix modulo mod
readonly long[] _pref2; // Hash on prefix modulo 2^64
// Constructor from string:
internal RollingHashedString(RollingHashPowers pows, string s, bool caseInsensitive = false)
{
_pows = pows;
_pref1 = new int[s.Length + 1];
_pref2 = new long[s.Length + 1];
const long capAVal = 'A';
const long capZVal = 'Z';
const long aADif = 'a' - 'A';
unsafe
{
fixed (char* c = s)
{
// Fill arrays with polynomial hashes on prefix
for (int i = 0; i < s.Length; ++i)
{
long v = c[i];
if (caseInsensitive && capAVal <= v && v <= capZVal)
{
v += aADif;
}
_pref1[i + 1] = (int)((_pref1[i] + v * _pows._pow1[i]) % RollingHashPowers._mod);
_pref2[i + 1] = _pref2[i] + v * _pows._pow2[i];
}
}
}
}
// Rollingnomial hash of subsequence [pos, pos+len)
// If mxPow != 0, value automatically multiply on base in needed power.
// Finally base ^ mxPow
internal Tuple<int, long> Apply(int pos, int len, int mxPow = 0)
{
int hash1 = _pref1[pos + len] - _pref1[pos];
long hash2 = _pref2[pos + len] - _pref2[pos];
if (hash1 < 0)
{
hash1 += RollingHashPowers._mod;
}
if (mxPow != 0)
{
hash1 = (int)((long)hash1 * _pows._pow1[mxPow - (pos + len - 1)] % RollingHashPowers._mod);
hash2 *= _pows._pow2[mxPow - (pos + len - 1)];
}
return Tuple.Create(hash1, hash2);
}
}
private readonly RollingHashPowers _rhp;
public RollingHash(int longestLength = 0)
{
_rhp = new RollingHashPowers();
if (longestLength > 0)
{
_rhp.EnsureLength(longestLength);
}
}
public string FindCommonSubstring(string a, string b, bool caseInsensitive = false)
{
// Calculate max neede power of base:
int mxPow = Math.Max(a.Length, b.Length);
_rhp.EnsureLength(mxPow);
// Create hashing objects from strings:
RollingHashedString hash_a = new RollingHashedString(_rhp, a, caseInsensitive);
RollingHashedString hash_b = new RollingHashedString(_rhp, b, caseInsensitive);
// Binary search by length of same subsequence:
int pos = -1;
int low = 0;
int minLen = Math.Min(a.Length, b.Length);
int high = minLen + 1;
var tupleCompare = Comparer<Tuple<int, long>>.Default;
while (high - low > 1)
{
int mid = (low + high) / 2;
List<Tuple<int, long>> hashes = new List<Tuple<int, long>>(a.Length - mid + 1);
for (int i = 0; i + mid <= a.Length; ++i)
{
hashes.Add(hash_a.Apply(i, mid, mxPow));
}
hashes.Sort(tupleCompare);
int p = -1;
for (int i = 0; i + mid <= b.Length; ++i)
{
if (hashes.BinarySearch(hash_b.Apply(i, mid, mxPow), tupleCompare) >= 0)
{
p = i;
break;
}
}
if (p >= 0)
{
low = mid;
pos = p;
}
else
{
high = mid;
}
}
// Output answer:
return pos >= 0
? b.Substring(pos, low)
: string.Empty;
}
}

shifting array elements to right?

I can't use a built-in function for this, I must use my own logic.
I've done element shifting to the left side, but the right side doesn't work for me. Not sure why.
My method for left:
public int[] shiftLeft(int[] arr) {
int[] demo = new int[arr.length];
int index = 0;
for (int i = 0; i < arr.length - 1; i++) {
demo[index] = arr[i + 1];
index++;
}
return demo;
}
and my attempt for the right shifting:
public int[] shiftRight(int[] arr) {
int[] demo = new int[arr.length];
int index = 0;
for (int i = arr.length - 1; i >= 0; i--) {
demo[index] = arr[(i - 1 > 0) ? i - 1 : 0];
index++;
}
return demo;
}
What am I doing wrong?
By shifting I mean:
you have an array, 1 2 3 4 5 6
Shifting it to left by one: 2 3 4 5 6 1
Shifting it to right by one: 6 1 2 3 4 5
//right shift with modulus
for (int i = 0; i < arr.length; i++) {
demo[(i+1) % demo.length] = arr[i];
}
The easiest way to go:
public int[] shiftLeft(int[] arr)
{
int[] demo = new int[arr.Length];
for (int i = 0; i < arr.Length - 1; i++)
{
demo[i] = arr[i + 1];
}
demo[demo.Length - 1] = arr[0];
return demo;
}
public int[] shiftRight(int[] arr)
{
int[] demo = new int[arr.Length];
for (int i = 1; i < arr.Length; i++)
{
demo[i] = arr[i - 1];
}
demo[0] = arr[demo.Length - 1];
return demo;
}
LINQ solution, just to add some diversity.
static int[] LeftShift(int[] array)
{
// all elements except for the first one... and at the end, the first one. to array.
return array.Skip(1).Concat(array.Take(1)).ToArray();
}
static int[] RightShift(int[] array)
{
// the last element (because we're skipping all but one)... then all but the last one.
return array.Skip(array.Length - 1).Concat(array.Take(array.Length - 1)).ToArray();
}
Probably not recommended if performance matters (for large arrays).
I realize that the OP is not supposed to use a "built-in function".
public static int[] shiftRight(int[] arr){
int[] demo = new int[arr.Length];
for (int i = 0; i <= arr.Length - 2; i++)
{
demo[i + 1] = arr[i];
}
demo[0] = arr[arr.Length - 1];
return demo;
}
The problem here is that you need to special case the left shift of the first element. For every element but the first the new index of the value will be oldIndex - 1. This is essentially what the loop is doing. However the first element has a new index of oldLength - 1. This needs to be special cased somewhere in the code base.
Try this,
public int[] ShiftRight(int[] arr)
{
int[] demo = new int[arr.Length];
for (int i = 0; i < arr.Length; i++) {
demo[i] = arr[i == 0 ? (arr.Length - 1) : (i - 1)];
}
return demo;
}
Use Arra.Copy...
public int[] shiftLeft(int[] arr) {
var result = new int[arr.Length];
Array.Copy(arr, 1, result, 0, arr.Length - 1);
result[arr.Length - 1] = arr[0];
return result;
}
public int[] shiftRight(int[] arr) {
var result = new int[arr.Length];
Array.Copy(arr, 0, result, 1, arr.Length - 1);
result[0] = arr[arr.Length - 1];
return result;
}
Usually I use this code. You can rewrites to the array extension method.
public static T[] Shift<T>(T[] array, int shiftValue)
{
var newArray = new T[array.Length];
shiftValue -= array.Length;
if(shiftValue < 0)
{
shiftValue*=-1;
}
for(var i=0; i<array.Length; i++)
{
var index = (i + shiftValue) % array.Length;
newArray[i] = array[index];
}
return newArray;
}
maybe this works for anyone seeing this post :
private int[] shiftLinear(int[] linArray, int shift){
int length = linArray.Length;
int[] shifted = new int[length];
shift = shift % length;
if (shift >= 0) {
for (int n = shift ; n < length; n++) shifted[n] = linArray[n-shift];
if (shift != 0) for (int n = 0; n < shift; n++) shifted[n] = linArray[length-1-n];
} else {
for (int n = 0 ; n < length+shift; n++) shifted[n] = linArray[n-shift];
for (int n = length+shift; n < length ; n++) shifted[n] = linArray[n-length-shift];
}
return shifted;
}
Without using external array;
public static int[] right(int[] A)
{
var tempo = A[0];
for(var i=0; i<A.Length-1; i++)
{
var yolo = A[i + 1];
A[i + 1] = tempo;
tempo = yolo;
}
A[0] = tempo;
return A;
}
public static int[] left(int[] A)
{
var tempo = A[A.Length - 1];
for (var i = A.Length - 1; i >0; i--)
{
var yolo = A[i - 1];
A[i -1] = tempo;
tempo = yolo;
}
A[A.Length - 1] = tempo;
return A;
}
public int[] shiftRight(int[] arr)
{
int[] demo = new int[arr.length];
Array.Copy(arr,arr.Length-1,demo,0,1); // Copy last position to first
Array.Copy(arr,0,demo,1,arr.Length-1); // Copy the rest shifted one
return demo;
}

Latest Codility Time Problems

Just got done with the latest Codility, passed it, but didnt get 100% on it
Here is the spec
A prefix of a string S is any leading contiguous part of S. For example, "c" and "cod" are prefixes of the string "codility". For simplicity, we require prefixes to be non-empty.
The product of prefix P of string S is the number of occurrences of P multiplied by the length of P. More precisely, if prefix P consists of K characters and P occurs exactly T times in S, then the product equals K * T.
For example, S = "abababa" has the following prefixes:
"a", whose product equals 1 * 4 = 4,
"ab", whose product equals 2 * 3 = 6,
"aba", whose product equals 3 * 3 = 9,
"abab", whose product equals 4 * 2 = 8,
"ababa", whose product equals 5 * 2 = 10,
"ababab", whose product equals 6 * 1 = 6,
"abababa", whose product equals 7 * 1 = 7.
The longest prefix is identical to the original string. The goal is to choose such a prefix as maximizes the value of the product. In above example the maximal product is 10.
In this problem we consider only strings that consist of lower-case English letters (a−z).
So basically, it is a string traverse problem. I was able to pass all the validation parts, but I lost on the time. Here is what I wrote
int Solution(string S)
{
int finalCount = 0;
for (int i = 0; i <= S.Length - 1; i++)
{
string prefix = S.Substring(0, i + 1);
int count = 0;
for (int j = 0; j <= S.Length - 1; j++)
{
if (prefix.Length + j <= S.Length)
{
string newStr = S.Substring(j, prefix.Length);
if (newStr == prefix)
{
count++;
}
}
if (j == S.Length - 1)
{
int product = count * prefix.Length;
if (product > finalCount)
{
finalCount = product;
}
}
}
}
return finalCount;
}
I know that the nested loop is killing me, but I cannot think of a way to traverse the "sections" of the string without adding the other loop.
Any help would be appreciated.
Naive brute-force solution takes O(N ** 3) time. Choose length from 1 to N, get a prefix of its length and count occurences by brute-force searching. Сhoosing length takes O(N) time and brute force takes O(N ** 2) time, totally O(N ** 3).
If you use KMP or Z-algo, you can find occurences in O(N) time, so the whole solution will be O(N ** 2) time.
And you can precalc occurences, so it will take O(N) + O(N) = O(N) time solution.
vector<int> z_function(string &S); //z-function, z[0] = S.length()
vector<int> z = z_function(S);
//cnt[i] - count of i-length prefix occurrences of S
for (int i = 0; i < n; ++i)
++cnt[z[i]];
//if cnt[i] is in S, cnt[i - 1] will be in S
int previous = 0;
for (int i = n; i > 0; --i) {
cnt[i] += previous;
previous = cnt[i];
}
Here's the blog post, explaining all O(N ** 3), O(N ** 2), O(N) solutions.
my effort was as follows trying to eliminate unnecessary string compares, i read isaacs blog but it is in c how would this translate to c#, i even went as far as using arrays everywhere to avoid the string immutability factor but there was no improvement
int Rtn = 0;
int len = S.Length;
if (len > 1000000000)
return 1000000000;
for (int i = 1; i <= len; i++)
{
string tofind = S.Substring(0, i);
int tofindlen = tofind.Length;
int occurencies = 0;
for (int ii = 0; ii < len; ii++)
{
int found = FastIndexOf(S, tofind.ToCharArray(), ii);
if (found != -1)
{
if ((found == 0 && tofindlen != 1) || (found >= 0))
{
ii = found;
}
++occurencies ;
}
}
if (occurencies > 0)
{
int total = occurencies * tofindlen;
if (total > Rtn)
{
Rtn = total;
}
}
}
return Rtn;
}
static int FastIndexOf(string source, char[] pattern, int start)
{
if (pattern.Length == 0) return 0;
if (pattern.Length == 1) return source.IndexOf(pattern[0], start);
bool found;
int limit = source.Length - pattern.Length + 1 - start;
if (limit < 1) return -1;
char c0 = pattern[0];
char c1 = pattern[1];
// Find the first occurrence of the first character
int first = source.IndexOf(c0, start, limit);
while ((first != -1) && (first + pattern.Length <= source.Length))
{
if (source[first + 1] != c1)
{
first = source.IndexOf(c0, ++first);
continue;
}
found = true;
for (int j = 2; j < pattern.Length; j++)
if (source[first + j] != pattern[j])
{
found = false;
break;
}
if (found) return first;
first = source.IndexOf(c0, ++first);
}
return -1;
}
I only got a 43... I like my code though! Same script in javascript got 56 for what it's worth.
using System;
class Solution
{
public int solution(string S)
{
int highestCount = 0;
for (var i = S.Length; i > 0; i--)
{
int occurs = 0;
string prefix = S.Substring(0, i);
int tempIndex = S.IndexOf(prefix) + 1;
string tempString = S;
while (tempIndex > 0)
{
tempString = tempString.Substring(tempIndex);
tempIndex = tempString.IndexOf(prefix);
tempIndex++;
occurs++;
}
int product = occurs * prefix.Length;
if ((product) > highestCount)
{
if (highestCount > 1000000000)
return 1000000000;
highestCount = product;
}
}
return highestCount;
}
}
This works better
private int MaxiumValueOfProduct(string input)
{
var positions = new List<int>();
int max = 0;
for (int i = 1; i <= input.Length; i++)
{
var subString = input.Substring(0, i);
int position = 0;
while ((position < input.Length) &&
(position = input.IndexOf(subString, position, StringComparison.OrdinalIgnoreCase)) != -1)
{
positions.Add(position);
++position;
}
var currentMax = subString.Length * positions.Count;
if (currentMax > max) max = currentMax;
positions.Clear();
}
return max;
}

Categories

Resources