Obtain the lexicographically smallest string possible, by using at most P points - c#

⦁ Replace and/or re-arrange characters of this given string to get the lexicographically smallest string possible. For this, you can perform the following two operations any number of times.
⦁ Swap any two characters in the string. This operation costs 1 point. (any two, need not be adjacent)
⦁ Replace a character in the string with any other lower case English letter. This operation costs 2 points.
Obtain the lexicographically smallest string possible, by using at most P points.
Input:
⦁ Two lines of input, first-line containing two integers N, P.
⦁ The second line contains a string S consisting of N characters.
Output:
Lexicographically smallest string obtained.
for e.g
Sample Input:
3 3
bba
Sample Output:
aab
Ive tried this but it doesnt contain P points i dont know how to do that can you guys please help me with that:
namespace Lexicographical
{
class GFG
{
// Function to return the lexicographically
// smallest String that can be formed by
// swapping at most one character.
// The characters might not necessarily
// be adjacent.
static String findSmallest(char[] s)
{
int len = s.Length;
// Store last occurrence of every character
int[] loccur = new int[26];
// Set -1 as default for every character.
for (int i = 0; i < 26; i++)
loccur[i] = -1;
for (int i = len - 1; i >= 0; --i)
{
// char index to fill
// in the last occurrence array
int chI = s[i] - 'a';
if (loccur[chI] == -1)
{
// If this is true then this
// character is being visited
// for the first time from the last
// Thus last occurrence of this
// character is stored in this index
loccur[chI] = i;
}
}
char[] sorted_s = s;
Array.Sort(sorted_s);
for (int i = 0; i < len; ++i)
{
if (s[i] != sorted_s[i])
{
// char to replace
int chI = sorted_s[i] - 'a';
// Find the last occurrence
// of this character.
int last_occ = loccur[chI];
// Swap this with the last occurrence
char temp = s[last_occ];
s[last_occ] = s[i];
s[i] = temp;
break;
}
}
return String.Join("", s);
}
// Driver code
public static void Main(String[] args)
{
String s = "abb";
Console.Write(findSmallest(s.ToCharArray()));
}
}
}
The output for this is abb but it should be aab...
I want to know how i can use above Question in this

Related

Creating strings from a template by replacing placeholders by all permutations of an input set

I want to make a simple generator of strings.
User inputs a "template" for string. Template can have placeholders in any place in it.
Then he inputs possible characters that can fit into any placeholder in string.
How it should work:
INPUT:
a.b.
123
OUTPUT:
[
"a1b1", "a1b2", "a1b3",
"a2b1", "a2b2", "a2b3",
"a3b1", "a3b2", "a3b3"
]
I found some of my old python code, but i don't understand it at all.
I split the input string to array of strings and array of dots.
Then I tried to increment just dots and each time just concat those two arrays in the right way.
But I found a new trouble.
string[] splitted = kt_NonCur.Split('.'); // array of constant strings
char[] nch = new char[splitted.Length - 1]; // array of new chars (generated)
char lgc = goodLetters.Last( ); // last good char
for( int i = 0; i < nch.Length - 1; i++ ) // set up all nch to first letter
nch[i] = goodLetters[0];
while( nch.Last( ) != lgc ) { // until last nch is set to last good char
outputData.Add($"{concatsplit(splitted, nch)}"); // concatsplit(s,n) concatenates two arrays into string
nch[0] = up(nch[0]); // up(char) gets next character from goodLetters. If there is no next, it returns first letter.
if( nch[0] == goodLetters[0] ) {
nch[1] = up(nch[1]);
if(nch[1] == goodLetters[0]){
nch[2] = up(nch[2]);
// .
// .
// .
}
}
}
And the problem is: I am facing a dilemma. Either find better way, or limit number of placeholders so that the code ladder is not too long. Of course I would add then some code that checks if it is the last and stop executing code for others, but I still would have to make
You can look at your problem this way: if you have P placeholders in your input string and the number of replacement characters is R, to construct every possibe output string you need at each step P numbers [0...R-1] (which can then serve as index into the replacement character list). Well, this is the definition of an integer with P digits in base R.
So let's write a helper class representing such integers:
class NDigitNumber
{
int[] _digits;
int _base;
// construct an integer with the specified numer of digits in the specified base
public NDigitNumber(int digits, int #base)
{
_digits = new int[digits];
_base = #base;
}
// get the digit at the specified position
public int this[int index] => _digits[index];
// increment the number, returns false on overflow
public bool Increment()
{
for (var pos = 0; pos < _digits.Length; pos++)
{
if (++_digits[pos] < _base)
break;
if (pos == _digits.Length-1)
return false;
for (var i = 0; i <= pos; i++)
_digits[i] = 0;
}
return true;
}
}
The Increment methods works like these mechanical counter devices where each digit wheel, when rotated from its maximum digit to the next, resets itself and all lower wheels to 0 and increments the next higher wheel.
Then we only have to iterate over all possible such integers to get the desired output:
var input = "a.b.";
var placeholder = '.';
var replacements = new[] { '1', '2', '3' };
// determine positions of placeholder in string
var placeholderPositions = new List<int>();
for (var i = 0; i < input.Length; i++)
{
if (input[i] == placeholder)
placeholderPositions.Add(i);
}
// iterate over all possible integers with
// placeholderPositions.Count digits
// in base replacements.Length
var number = new NDigitNumber(placeholderPositions.Count, replacements.Length);
do
{
var result = new StringBuilder(input);
for (var i = 0; i < placeholderPositions.Count; i++)
result[placeholderPositions[i]] = replacements[number[i]];
Console.WriteLine(result.ToString());
} while(number.Increment());
Output:
a1b1
a2b1
a3b1
a1b2
a2b2
a3b2
a1b3
a2b3
a3b3
Based on accepted answer of this post:
public static IEnumerable<string> Combinations(string template, string str, char placeholder)
{
int firstPlaceHolder = template.IndexOf(placeholder);
if (firstPlaceHolder == -1)
return new string[] { template };
string prefix = template.Substring(0, firstPlaceHolder);
string suffix = template.Substring(firstPlaceHolder + 1);
var recursiveCombinations = Combinations(suffix, str, placeholder);
return
from chr in str
from recSuffix in recursiveCombinations
select prefix + chr + recSuffix;
}
Usage:
List<string> combinations = Combinations("a.b.", "123", '.').ToList();

Skipping a range of values in for loop C#

I'm trying to cycle through chars in a string.
string cycleMe = "Hi StackOverflow! Here is my string."
However, I want to skip over certain ranges of indexes. The ranges I want to skip over are stored in a List of objects, delims.
List<Delim> delims = delimCreator();
To retrieve each starting index and ending index for a range, I have to write a loop that accesses each "delim":
delims[0].getFirstIndex() //results in, say, index 2
delims[0].getLastIndex() //results in, say, index 4
delims[1].getFirstIndex() //results in, say, index 5
delims[1].getLastIndex() //results in, say, index 7
(there can be infinitely many "delim" objects in play)
If the above were my list, I'd want to print the string cycleMe, but skip all the chars between 2 and 4 (inclusive) and 5 and 7 (inclusive).
Expected output using the numbers above:
HiOverflow! Here is my string.
Here is the code I have written so far. It loops far more often than I'd expect (it loops ~x2 the number of characters in the string). Thanks in advance! =)
List<Delim> delims = delimAggregateInator(displayTextRaw);
for (int x = 0; x < cycleMe.Length;x++){
for (int i = 0; i < delims.Count; i++){
if (!(x >= delims[i].getFirstIndex() && x <= delims[i].getLastIndex())){
Debug.Log("test");
}
}
I assume that by skipping you meant you want to omit those characters from the original string. If that is the case, you can try Aggregate extension method like below.
string result = delims.Aggregate<Delim, string>(cycleMe, (str, d) => cycleMe = cycleMe.Remove(d.FirstIndex, (d.LastIndex - d.FirstIndex) + 1));
Make sure that the delim list is in the proper order.
Solution might be converting the string to char array, replacing the desired parts to spaces, and converting the output back to string.
Here is the modified version of your code:
string cycleMe = "Hi StackOverflow! Here is my string."
var charArray = cycleMe.ToCharArray(); // Converting to char array
List<Delim> delims = delimAggregateInator(displayTextRaw);
for (int x = 0; x < cycleMe.Length;x++){
for (int i = 0; i < delims.Count; i++){
// ORIGINAL: if (!(x >= delims[i].getFirstIndex() && x <= delims[i].getLastIndex())){
if (x >= delims[i].getFirstIndex() && x <= delims[i].getLastIndex()){
Debug.Log("test");
charArray[x] = ' '; // Replacing the item with space
}
}
string output = new string(charArray); // Converting back to string
P.S. This is probably not the most optimal solution but at least it should work.
You should use LINQ for that
struct Delim
{
public int First { get; set; }
public int Last { get; set; }
}
static void Main(string[] args)
{
string cycleMe = "Hi StackOverflow! Here is my string.";
var delimns = new List<Delim> { new Delim { First=2, Last=4}, new Delim { First = 5, Last = 7 } };
var cut = cycleMe.Where((c, i) =>
!delimns.Any(d => i >= d.First && i <= d.Last));
Console.WriteLine(new string(cut.ToArray());
}
That means I am basically only selecting letters, at positions which are not part of any cutting range.
Also: Fix your naming. A delimiter is a character, not a position (numeric)

shortest substring of string in C#

I try to write I program that given a string comprised of lowercase lettes in the range ascii[a-z] and determine the length of the smallest substring that contains all of the letters present on the string.
but I got Terminated due to timeout.
How can I improve the sulotion?
I tried:
public static int shortestSubstring(string s){
int n = s.Length;
int max_distinct = max_distinct_char(s, n);
int minl = n;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
String subs = null;
if (i < j)
subs = s.Substring(i, s.Length - j);
else
subs = s.Substring(j, s.Length - i);
int subs_lenght = subs.Length;
int sub_distinct_char = max_distinct_char(subs, subs_lenght);
if (subs_lenght < minl && max_distinct == sub_distinct_char)
{
minl = subs_lenght;
}
}
}
return minl;
}
private static int max_distinct_char(String s, int n)
{
int[] count = new int[NO_OF_CHARS];
for (int i = 0; i < n; i++)
count[s[i]]++;
int max_distinct = 0;
for (int i = 0; i < NO_OF_CHARS; i++)
{
if (count[i] != 0)
max_distinct++;
}
return max_distinct;
}
}
I believe there is an O(n) solution to this problem as follows:
We first traverse the string to find out how many distinct characters are in it. After this, we initialize two pointers denoting the left and right index of the substring to 0. We also keep an array counting the number of each character currently present in the substring. If not all characters are contained, we increase the right pointer in order to get another character. If all characters are contained, we increase the left pointer in order to possibly get a smaller substring. Since either the left or right pointer increase at each step, this algorithm should run in O(n) time.
For inspiration for this algorithm, see Kadane's algorithm for the maximum subarray problem.
Unfortunately, I do not know C#. However, I have written a Java solution (which hopefully has similar syntax). I haven't stress tested this rigorously so it's possible I missed an edge case.
import java.io.*;
public class allChars {
public static void main (String[] args) throws IOException {
BufferedReader br = new BufferedReader (new InputStreamReader(System.in));
String s = br.readLine();
System.out.println(shortestSubstring(s));
}
public static int shortestSubstring(String s) {
//If length of string is 0, answer is 0
if (s.length() == 0) {
return 0;
}
int[] charCounts = new int[26];
//Find number of distinct characters in string
int count = 0;
for (int i = 0; i < s.length(); i ++) {
char c = s.charAt(i);
//If new character (current count of it is 0)
if (charCounts[c - 97] == 0) {
//Increase count of distinct characters
count ++;
//Increase count of this character to 1
//Can put inside if statement because don't care if count is greater than 1 here
//Only care if character is present
charCounts[c - 97]++;
}
}
int shortestLen = Integer.MAX_VALUE;
charCounts = new int[26];
//Initialize left and right pointers to 0
int left = 0;
int right = 0;
//Substring already contains first character of string
int curCount = 1;
charCounts[s.charAt(0)-97] ++;
while (Math.max(left,right) < s.length()) {
//If all distinct characters present
if (curCount == count) {
//Update shortest length
shortestLen = Math.min(right - left + 1, shortestLen);
//Decrease character count of left character
charCounts[s.charAt(left) - 97] --;
//If new count of left character is 0
if (charCounts[s.charAt(left) - 97] == 0) {
//Decrease count of distinct characters
curCount --;
}
//Increment left pointer to create smaller substring
left ++;
}
//If not all characters present
else {
//Increment right pointer to get another character
right ++;
//If character is new (old count was 0)
if (right < s.length() && charCounts[s.charAt(right) - 97]++ == 0) {
//Increment distinct character count
curCount ++;
}
}
}
return shortestLen;
}
}
I hope I understand it right, here's the code to get the smallest string.
string str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec dictum elementum condimentum. Aliquam commodo ipsum enim. Vivamus tincidunt feugiat urna.";
char[] operators = { ' ', ',', '.', ':', '!', '?', ';' };
string[] vs = str.Split(operators);
string shortestWord = vs[0];
for (int i = 0; i < vs.Length; i++)
{
if (vs[i].Length < shortestWord.Length && vs[i] != "" && vs[i] != " ")
{
shortestWord = vs[i];
}
}
Console.WriteLine(shortestWord);
This seems to be an O(n^2) problem. This is not ideal; however, we can do several things to avoid testing sub-strings that cannot be valid candidates.
I suggest to return the sub-string itself, instead of its length. This helps to validate the result.
public static string ShortestSubstring(string input)
We begin by counting the occurrence of each character in the range ['a' .. 'z']. We can subtract 'a' from a character to get its zero-based index.
var charCount = new int[26];
foreach (char c in input) {
charCount[c - 'a']++;
}
The shortest possible sub-string is equal to the count of distinct characters in the input.
int totalDistinctCharCount = charCount.Where(c => c > 0).Count();
To count the number of distinct characters in the sub-string, we need the following Boolean array:
var hasCharOccurred = new bool[26];
Now, let's test sub-strings starting at different positions. The maximum start position must allow sub-strings at least as long as the totalDistinctCharCount (the shortest possible sub-string).
string shortest = input;
for (int start = 0; start <= input.Length - totalDistinctCharCount; start++) {
...
}
return shortest;
Inside this loop we have another loop counting the distinct characters of the sub-string. Note that we work directly on the input string to avoid creating a lot of new strings. We only need to test sub-strings that are shorter than any shortest one found before. Therefore the inner loop uses Math.Min(input.Length, start + shortest.Length - 1) as limit. Content of loop (in place of the ... in the upper code snippet):
int distinctCharCount = 0;
// No need to go past the length the previously found shortest.
for (int i = start; i < Math.Min(input.Length, start + shortest.Length - 1); i++) {
int chIndex = input[i] - 'a';
if (!hasCharOccurred[chIndex]) {
hasCharOccurred[chIndex] = true;
distinctCharCount++;
if (distinctCharCount == totalDistinctCharCount) {
shortest = input.Substring(start, i - start + 1);
break; // Found a shorter one, exit this inner loop.
}
}
}
// We cannot omit characters occurring only once
if (charCount[input[start] - 'a'] == 1) {
break; // Start cannot go beyond this point.
}
// Clear hasCharOccurred, to avoid creating a new array evey time.
for (int i = 0; i < 26; i++) {
hasCharOccurred[i] = false;
}
A further optimization is that we stop as soon as we encounter a character at the start position occurring only once in the input string (charCount[input[start] - 'a'] == 1). Since every distinct character of the input must be present in the sub-string, this one must be part of the sub-string.
We can print the result in the console with
string shortest = ShortestSubstring(TestString);
Console.WriteLine($"Shortest, Length = {shortest.Length}, \"{shortest}\"");

Get first alphanumeric or special character in string from start index

Say I have a string such as:
ma, 100 or, ma, word, or even ma. , *+ etc.
How can I find the position of the first character that is not some form of punctuation (i.e full stop, comma, colon, semi-colon) or whitespace, after an index. So, in the last example above, I'd want to get the position of * when I pass in 1 as a start index (zero-based).
Create an array of the characters that you want to match and call String.IndexOfAny
For example:
const string GoodCharsStr =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxy";
readonly char[] GoodChars = GoodCharsStr.ToCharArray();
string search = "ma, 100";
int position = search.IndexOfAny(GoodChars, 1);
if (position == -1)
{
// not found
}
char foundChar = search[position];
You'll need to define what exactly a special character is.
If it's a non-consecutive set (according to ASCII ordering, see http://www.asciitable.com/) then you'll need to define a new allowed character set and check against that set.
Something like this should work:
public const string allowed = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890.,";
public int RetrieveIndex(string input, int startIndex)
{
for (var x = startIndex; x < input.length; x++)
{
if (allowed.IndexOf(input[x])==-1)
{
return x;
}
}
return -1;
}
However, if it is a consecutive set as defined by the ASCII standard:
Just figure out which range is considered acceptable or special and check against that by converting the character to an integer and checking if it lies within the range. This would prove faster than the calls to allowed.IndexOf(...).
You can use a method like this
public static int GetFirstNonPunctuationCharIndex(string input, int startIndex, char[] punctuation)
{
//Move the startIndex forward one because we ignore the index user set
startIndex = startIndex + 1 < input.Length ? startIndex + 1 : input.Length;
for (int i = startIndex ; i < input.Length; i++)
{
if (!punctuation.Contains(input[i]) && !Char.IsWhiteSpace(input[i]))
{
return i;
}
}
return -1;
}
You would call it by passing in the string, starting index, and an array of characters you consider to be punctuation.
string myString = #"ma. , *+";
char[] puncArray = new char[4] { '.', ',', ';', ':' };
int index = GetFirstNonPunctuationCharIndex(myString, 1, puncArray)
Normally I'd use the Char.IsPunctuation method but apparently it considers * to be a punctuation character so you'll have to roll your own like above.

Finding Matching Strings Algorithm

I have very long 5 strings (the number of strings may change).There is no fixed format for these strings. I will provide a number which will indicate the length of the substring. I want to find the matching substrings with the given length. For example the strings are:
1. abcabcabc
2. abcasdfklop
string length: 3
Given these values the output will be something like this:
Match #1:
Matched string : "abc"
Matches in first string: 3
Matching positions: 0,3,6
Matches in second string: 1
Match positions: 0
Match #2:
Matched string : "bca"
Matches in first string: 2
Matching positions: 1,4
Matches in second string: 1
Match positions: 1
I managed to do it in 4 foreach statement. But it seemed to me too unefficient. Especially if the input sizes are very big.Is there any suggestion or short way to manage this more efficient in c#?
You can do this with a suffix array. (Suffix trees will work fine too, but they require a bit more space, time, and care in implementation.)
Concatenate your two strings, separating them with a character that occurs in neither one. Then build a suffix array. Then you can read off your answer.
Standard suffix arrays give you a lexicographically sorted array of pointers to suffixes of the string together with a "longest common prefix length" array telling you how long the longest common prefix of two lexicographically consecutive suffixes is.
It is fairly straightforward to use the longest common prefix length array to get the information you want; find all maximal subarrays of the longest common prefix length array for which the longest common prefix length is at least the query length, then, for each one that has a match both in the first string and in the second string, report the appropriate prefix and report that it occurs K+1 times, where K is the length of the maximal subarray.
Another approach that's easier to code is to hash all substrings of the appropriate length. You can do this easily with any rolling hash function. Store a dynamic array of pointers into the strings for each hash; once you've hashed all the strings, iterate over all of the hashes that came up and look for matches. You'll need to deal with the false positives somehow; one (probabilistic) approach is to use several hash functions until the false positive probability is acceptably small. Another approach, which is likely only acceptable in the case where you have few matches, is to compare the strings directly.
If you managed to do this in 4 foreach statements that are not nested then you should be good and you probably don’t need to optimize.
Here is something I’d try.
Create a structure that looks something like this
class SubString
{
string str;
int position;
}
Divide both strings into all possible substrings and store these into one array. This has a O(n2) complexity.
Now sort these arrays by string length ( O(n*log(n)) complexity) and go through both of these to identify matches.
You’ll need additional structure to hold the results and this probably needs some more tweaking but you see where this is going.
You could use a variant of suffix tree to solve this problem. http://en.wikipedia.org/wiki/Longest_common_substring_problem
Also check this out: Algorithm: Find all common substrings between two strings where order is preserved
If using very large strings, memory may become a problem. The code below finds the longest common substring and writes over the variable containing smaller common substrings, but could easily be altered to push the index and length to a list which is then returned as an array of strings.
This is refactored C++ code from Ashutosh Singh at https://iq.opengenus.org/longest-common-substring-using-rolling-hash/ - 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;
}
}

Categories