Skip to content

Commit cd6ec80

Browse files
Add z-block substring search algorithm (TheAlgorithms#360)
Co-authored-by: Kalkwst <[email protected]>
1 parent bb5c243 commit cd6ec80

File tree

3 files changed

+93
-0
lines changed

3 files changed

+93
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using Algorithms.Strings;
2+
using NUnit.Framework;
3+
4+
namespace Algorithms.Tests.Strings
5+
{
6+
public class ZblockSubstringSearchTest
7+
{
8+
[TestCase("abc", "abcdef", 1)]
9+
[TestCase("xxx", "abxxxcdexxxf", 2)]
10+
[TestCase("aa", "waapaaxcdaalaabb", 4)]
11+
[TestCase("ABC", "ABAAABCDBBABCDDEBCABC", 3)]
12+
[TestCase("xxx", "abcdefghij", 0)]
13+
[TestCase("aab", "caabxaaaz", 1)]
14+
[TestCase("abc", "xababaxbabcdabx", 1)]
15+
[TestCase("GEEK", "GEEKS FOR GEEKS", 2)]
16+
[TestCase("ground", "Hello, playground!", 1)]
17+
public void Test(string pattern, string text, int expectedOccurences)
18+
{
19+
var occurencesFound = ZblockSubstringSearch.FindSubstring(pattern, text);
20+
Assert.AreEqual(expectedOccurences, occurencesFound);
21+
}
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
namespace Algorithms.Strings
2+
{
3+
/// <summary>Implementation Z-block substring search.
4+
/// </summary>
5+
public static class ZblockSubstringSearch
6+
{
7+
/// <summary>
8+
/// This algorithm finds all occurrences of a pattern in a text in linear time - O(m+n).
9+
/// </summary>
10+
public static int FindSubstring(string pattern, string text)
11+
{
12+
var concatStr = $"{pattern}${text}";
13+
var patternLength = pattern.Length;
14+
var n = concatStr.Length;
15+
var zArray = new int[n];
16+
17+
var left = 0;
18+
var right = 0;
19+
20+
for(var i = 1; i < n; i++)
21+
{
22+
if(i > right)
23+
{
24+
left = i;
25+
right = ComputeNewRightValue(concatStr, n, left, i);
26+
27+
zArray[i] = right - left;
28+
right--;
29+
}
30+
else
31+
{
32+
var k = i - left;
33+
if (zArray[k] < (right - i + 1))
34+
{
35+
zArray[i] = zArray[k];
36+
}
37+
else
38+
{
39+
left = i;
40+
right = ComputeNewRightValue(concatStr, n, left, right);
41+
zArray[i] = right - left;
42+
right--;
43+
}
44+
}
45+
}
46+
47+
var found = 0;
48+
foreach(var z_value in zArray)
49+
{
50+
if(z_value == patternLength)
51+
{
52+
found++;
53+
}
54+
}
55+
56+
return found;
57+
}
58+
59+
private static int ComputeNewRightValue(string concatStr, int n, int left, int right)
60+
{
61+
while (right < n && concatStr[right - left].Equals(concatStr[right]))
62+
{
63+
right++;
64+
}
65+
66+
return right;
67+
}
68+
}
69+
}

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ find more than one implementation for the same objective but using different alg
172172
* [Hamming Distance](./Algorithms/Strings/HammingDistance.cs)
173173
* [Jaro Similarity](./Algorithms/Strings/JaroSimilarity.cs)
174174
* [Jaro-Winkler Distance](./Algorithms/Strings/JaroWinklerDistance.cs)
175+
* [Z-block substring search](./Algorithms/Strings/ZblockSubstringSearch.cs)
175176
* [Other](./Algorithms/Other)
176177
* [Fermat Prime Checker](./Algorithms/Other/FermatPrimeChecker.cs)
177178
* [Sieve of Eratosthenes](./Algorithms/Other/SieveOfEratosthenes.cs)

0 commit comments

Comments
 (0)